简体   繁体   English

如果定义了超类__new__,则不调用子类__init__

[英]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 of cls , 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM