请参阅以下ipython会话:
$ ipython --no-banner
In [1]: class foo(object):
...: def __new__(self, *args, **kwargs):
...: print 'in superclass __new__'
...: return self
...:
...: class bar(foo):
...: def __init__(self, *args, **kwargs):
...: print 'in subclass __init__'
...: self.val = 42
...:
In [2]: b = bar()
in superclass __new__
In [3]: b.val
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-4-c55d38c9d4d9> in <module>()
----> 1 b.val
AttributeError: type object 'bar' has no attribute 'val'
这里发生了什么?为什么在__new__
中定义foo
会阻止__init__
在bar
中投放?
答案 0 :(得分:3)
您将从__new__
返回无效值。引用the documentation:
如果
__new__()
返回 cls 的实例,则会调用新实例的__init__()
方法...如果__new__()
未返回实例 cls ,然后不会调用新实例的__init__()
方法。
请注意__new__
的第一个参数是一个类,而不是一个对象。 __new__
的工作是分配对象,通常是通过调用super().__new__
。
试试这个:
class foo(object):
def __new__(cls, *args, **kwargs):
print 'in superclass __new__'
return super(foo, cls).__new__(cls, *args, **kwargs)
class bar(foo):
def __init__(self, *args, **kwargs):
print 'in subclass __init__'
self.val = 42
b = bar()
print b
答案 1 :(得分:3)
来自datamodel文档:
如果
__new__()
未返回cls
的实例,则不会调用新实例的__init__()
方法。
所以,请再试一次:
class foo(object):
def __new__(cls, *args, **kwargs):
print 'in superclass __new__'
return super(foo, cls).__new__(cls, *args, **kwargs)
class bar(foo):
def __init__(self, *args, **kwargs):
print 'in subclass __init__'
self.val = 42
答案 2 :(得分:3)
您的__new__
功能签名意味着您不太了解发生了什么。 __new__
的第一个参数是类,调用它self
通常用于实例应该是一个警告:{{1是构造函数,实例尚不存在。所以会发生什么事情,你要返回一个与类不同的类型的对象(实际上 类,所以类型为__new__
)因此, type
已被跳过!你想要这样的东西:
__init__