[英]Subclass __init__ is not called if superclass __new__ is defined
See the following ipython session: 请参阅以下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'
What is going on here? 这里发生了什么? Why does defining
__new__
in foo
prevent the __init__
from running in bar
? 为什么在
foo
中定义__new__
阻止__init__
在bar
运行?
You are returning an invalid value from __new__
. 您将从
__new__
返回无效值。 Quoting the documentation : 引用文档 :
If
__new__()
returns an instance of cls , then the new instance's__init__()
method will be invoked ... If__new__()
does not return an instance of cls , then the new instance's__init__()
method will not be invoked.如果
__new__()
返回cls的实例,则将调用新实例的__init__()
方法...如果__new__()
未返回cls的实例,则不会调用新实例的__init__()
方法。
Note that the first argument to __new__
is a class, not an object. 请注意,
__new__
的第一个参数是一个类,而不是一个对象。 __new__
's job is to allocate the object, often by calling super().__new__
. __new__
的工作是分配对象,通常是调用super().__new__
。
Try this: 尝试这个:
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
From the datamodel documentation: 从datamodel文档:
If
__new__()
does not return an instance ofcls
, then the new instance's__init__()
method will not be invoked.如果
__new__()
没有返回cls
的实例,则不会调用新实例的__init__()
方法。
So, try again like this: 所以,再试一次:
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
Your __new__
function signature implies you don't quite understand what is going on. 你的
__new__
函数签名意味着你不太明白发生了什么。 The first argument to __new__
will be the class , calling it self
which is conventionally used for the instance should be a warning: __new__
is a constructor, the instance doesn't exist yet . __new__
的第一个参数是类 ,调用它self
通常用于实例的应该是一个警告: __new__
是构造函数,实例还不存在 。 So what happens is you are returning an object that isn't the same type as the class, (it is the class in fact, so it is of type type
) thus, __init__
is skipped! 那么你要返回的是一个与类不同类型的对象(实际上它是类,所以它是类型
type
)因此, __init__
被跳过了! You want something like this: 你想要这样的东西:
In [4]: 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
...:
In [5]: b = Bar()
in superclass __new__
in subclass __init__
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.