Python:在__new__中覆盖__init__参数
我有一个 __new__
方法,内容如下:
class MyClass(object):
def __new__(cls, *args):
new_args = []
args.sort()
prev = args.pop(0)
while args:
next = args.pop(0)
if prev.compare(next):
prev = prev.combine(next)
else:
new_args.append(prev)
prev = next
if some_check(prev):
return SomeOtherClass()
new_args.append(prev)
return super(MyClass, cls).__new__(cls, new_args)
def __init__(self, *args):
...
不过,这样做会出现一个弃用警告:
DeprecationWarning: object.__new__() takes no parameters
SomeOtherClass
可以在处理参数时选择性地创建,这就是为什么这些参数是在 __new__
中处理,而不是在 __init__
中处理的原因。
那么,最好的方法是什么来把 new_args
传递给 __init__
呢?
否则,我就得在 __init__
中重复处理参数(没有 some_check
的情况下)。
4 个回答
2
编辑: 我找到了一种更好的解决方案 - 之前的方法表现得不够稳定。
我通过偶然发现了一些意想不到的简单行为,解决了我自己的问题:
return cls(*new_args)
而不是
return super(MyClass, cls).__new__(cls, *new_args)
只要 new_args
和传给 __new__
的原始参数不一样,就不会出现我预期中的无限递归。
2
既然你不一定需要创建一个 MyClass 的对象,那为什么不把创建对象的过程放到一个单独的函数里呢,比如叫 new(*args)
,这个函数可以根据需要返回一个 MyClass
或者 SomeOtherClass
的对象呢?
这样做会更整洁,因为你可以确定每次调用 MyClass() 时,都会得到一个 MyClass 的对象,而不是可能得到 SomeOtherClass,这样就不会让人感到困惑了。
10
我最后选择的解决方案是修改新创建的对象,在__new__
里进行调整,并完全去掉__init__
方法:
def __new__(cls, *args):
... # as above
new_self = super(MyClass, cls).__new__(cls)
new_self.args = new_args
return new_self
#def __init__(self, *args):
# self.args = args