__init__()应该调用父类的__init__()吗?

时间:2021-01-12 18:21:42

I'm used that in Objective-C I've got this construct:

我在Objective-C中使用了这个结构:

- (void)init {
    if (self = [super init]) {
        // init class
    }
    return self;
}

Should Python also call the parent class's implementation for __init__?

Python是否也应该调用父类的实现来进行__init__?

class NewClass(SomeOtherClass):
    def __init__(self):
        SomeOtherClass.__init__(self)
        # init class

Is this also true/false for __new__() and __del__()?

对于__new__()和__del__(),这也是正确的吗?

Edit: There's a very similar question: Inheritance and Overriding __init__ in Python

编辑:有一个非常相似的问题:在Python中继承和重写__init__。

6 个解决方案

#1


48  

In Python, calling the super-class' __init__ is optional. If you call it, it is then also optional whether to use the super identifier, or whether to explicitly name the super class:

在Python中,调用超类的__init__是可选的。如果您调用它,那么也可以选择是否使用超级标识符,或者是否显式地命名超类:

object.__init__(self)

In case of object, calling the super method is not strictly necessary, since the super method is empty. Same for __del__.

在对象的情况下,调用super方法并不是必需的,因为超级方法是空的。__del__相同。

OTOH, for __new__, you should indeed call the super method, and use its return as the newly-created object - unless you explicitly want to return something different.

对于__new__,您确实应该调用super方法,并使用它作为新创建的对象的返回——除非您明确地想要返回一些不同的东西。

#2


109  

If you need something from super's __init__ to be done in addition to what is being done in the current class's __init__, you must call it yourself, since that will not happen automatically. But if you don't need anything from super's __init__, no need to call it. Example:

如果您需要从super的__init__中得到一些东西,除了当前类的__init__中所做的之外,您必须自己调用它,因为这不会自动发生。但是如果你不需要任何超级的东西,就不用管它了。例子:

>>> class C(object):
    def __init__(self):
        self.b = 1


>>> class D(C):
    def __init__(self):
        super().__init__() # in Python 2 use super(D, self).__init__()
        self.a = 1


>>> class E(C):
    def __init__(self):
        self.a = 1


>>> d = D()
>>> d.a
1
>>> d.b  # This works because of the call to super's init
1
>>> e = E()
>>> e.a
1
>>> e.b  # This is going to fail since nothing in E initializes b...
Traceback (most recent call last):
  File "<pyshell#70>", line 1, in <module>
    e.b  # This is going to fail since nothing in E initializes b...
AttributeError: 'E' object has no attribute 'b'

__del__ is the same way, (but be wary of relying on __del__ for finalization - consider doing it via the with statement instead).

__del__是同样的方法,(但是要小心依赖于__del__来完成最后的定稿——考虑通过使用语句来完成它)。

I rarely use __new__. I do all the initialization in __init__.

我很少使用__new__。我在__init__中完成所有初始化。

#3


65  

In Anon's answer:
"If you need something from super's __init__ to be done in addition to what is being done in the current class's __init__ , you must call it yourself, since that will not happen automatically"

在Anon的回答中:“如果你需要从super的__init__中得到一些东西,除了在当前类的__init__中所做的事情之外,你必须自己调用它,因为这不会自动发生。”

It's incredible: he is wording exactly the contrary of the principle of inheritance.

令人难以置信的是:他的措辞恰好与继承原则正好相反。


It is not that "something from super's __init__ (...) will not happen automatically" , it is that it WOULD happen automatically, but it doesn't happen because the base-class' __init__ is overriden by the definition of the derived-clas __init__

这并不是说“超级的__init__(…)不会自动发生”,而是它会自动发生,但它不会发生,因为基类的__init__被定义为derived-clas __init__。

So then, WHY defining a derived_class' __init__ , since it overrides what is aimed at when someone resorts to inheritance ??

因此,为什么要定义一个derived_class的__init__,因为它覆盖了当某人使用继承时的目标?

It's because one needs to define something that is NOT done in the base-class' __init__ , and the only possibility to obtain that is to put its execution in a derived-class' __init__ function.
In other words, one needs something in base-class' __init__ in addition to what would be automatically done in the base-classe' __init__ if this latter wasn't overriden.
NOT the contrary.

因为我们需要定义在基类__init__中没有完成的事情,而获得这一功能的惟一可能是将其执行置于派生类的__init__函数中。换句话说,一个人在基础课程中需要一些东西,除了在基础课程中自动完成的内容之外,如果后者不是overriden的话。而不是相反。


Then, the problem is that the desired instructions present in the base-class' __init__ are no more activated at the moment of instantiation. In order to offset this inactivation, something special is required: calling explicitly the base-class' __init__ , in order to KEEP , NOT TO ADD, the initialization performed by the base-class' __init__ . That's exactly what is said in the official doc:

然后,问题是在基类__init__中显示的所需指令在实例化时不再被激活。为了抵消这种失活,需要一些特殊的东西:明确地调用基类的__init__,以便保持,而不是添加,由base类的__init__执行的初始化。这就是在官方文件中所说的:

An overriding method in a derived class may in fact want to extend rather than simply replace the base class method of the same name. There is a simple way to call the base class method directly: just call BaseClassName.methodname(self, arguments).
http://docs.python.org/tutorial/classes.html#inheritance

派生类中的重写方法实际上可能希望扩展而不是简单地替换相同名称的基类方法。有一种直接调用基类方法的简单方法:只调用BaseClassName。methodname(自我,参数)。http://docs.python.org/tutorial/classes.html继承

That's all the story:

这是所有的故事:

  • when the aim is to KEEP the initialization performed by the base-class, that is pure inheritance, nothing special is needed, one must just avoid to define an __init__ function in the derived class

    当目标是保持基类所执行的初始化时,这是纯继承,不需要什么特殊的东西,必须避免在派生类中定义__init__函数。

  • when the aim is to REPLACE the initialization performed by the base-class, __init__ must be defined in the derived-class

    当目标是替换base类执行的初始化时,__init__必须在derived类中定义。

  • when the aim is to ADD processes to the initialization performed by the base-class, a derived-class' __init__ must be defined , comprising an explicit call to the base-class __init__

    当目标是将进程添加到由base类执行的初始化时,必须定义一个derived类的__init__,其中包含对基类__init__的显式调用。


What I feel astonishing in the post of Anon is not only that he expresses the contrary of the inheritance theory, but that there have been 5 guys passing by that upvoted without turning a hair, and moreover there have been nobody to react in 2 years in a thread whose interesting subject must be read relatively often.

我觉得惊人后不久他不仅表达了相反的遗传理论,但这已经有5人路过upvoted毫不畏惧,而且已经有2年没有人反应在一个有趣的主题必须经常阅读相对的线程。

#4


17  

Edit: (after the code change)
There is no way for us to tell you whether you need or not to call your parent's __init__ (or any other function). Inheritance obviously would work without such call. It all depends on the logic of your code: for example, if all your __init__ is done in parent class, you can just skip child-class __init__ altogether.

编辑:(在代码更改之后)我们没有办法告诉您是否需要调用您父母的__init__(或任何其他函数)。显然,如果没有这样的召唤,继承权将会发挥作用。这完全取决于代码的逻辑:例如,如果所有的__init__都是在父类中完成的,那么您可以完全跳过子类__init__。

consider the following example:

考虑下面的例子:

>>> class A:
    def __init__(self, val):
        self.a = val


>>> class B(A):
    pass

>>> class C(A):
    def __init__(self, val):
        A.__init__(self, val)
        self.a += val


>>> A(4).a
4
>>> B(5).a
5
>>> C(6).a
12

#5


4  

There's no hard and fast rule. The documentation for a class should indicate whether subclasses should call the superclass method. Sometimes you want to completely replace superclass behaviour, and at other times augment it - i.e. call your own code before and/or after a superclass call.

没有硬性规定。类的文档应该指出子类是否应该调用超类方法。有时,您希望完全替换超类行为,而在其他时候则需要增加它——即在超类调用之前和/或之后调用自己的代码。

Update: The same basic logic applies to any method call. Constructors sometimes need special consideration (as they often set up state which determines behaviour) and destructors because they parallel constructors (e.g. in the allocation of resources, e.g. database connections). But the same might apply, say, to the render() method of a widget.

更新:同样的基本逻辑适用于任何方法调用。构造函数有时需要特殊的考虑(因为它们通常设置状态决定行为)和析构函数,因为它们是并行构造函数(例如,在资源分配中,例如数据库连接)。但是,对于小部件的render()方法,同样的方法也适用。

Further update: What's the OPP? Do you mean OOP? No - a subclass often needs to know something about the design of the superclass. Not the internal implementation details - but the basic contract that the superclass has with its clients (using classes). This does not violate OOP principles in any way. That's why protected is a valid concept in OOP in general (though not, of course, in Python).

进一步更新:OPP是什么?你是说OOP吗?不——子类通常需要了解超类的设计。不是内部实现细节,而是超类与客户端的基本契约(使用类)。这并不违反OOP原则。这就是为什么在OOP中保护是一个有效的概念(当然,当然不是在Python中)。

#6


3  

IMO, you should call it. If your superclass is object, you should not, but in other cases I think it is exceptional not to call it. As already answered by others, it is very convenient if your class doesn't even have to override __init__ itself, for example when it has no (additional) internal state to initialize.

IMO,你应该叫它。如果你的超类是对象,你不应该这样做,但在其他情况下,我认为不调用它是异常的。正如其他人已经回答的那样,如果您的类甚至不需要重写__init__本身,就非常方便,例如,当它没有(额外的)内部状态来初始化时。

#1


48  

In Python, calling the super-class' __init__ is optional. If you call it, it is then also optional whether to use the super identifier, or whether to explicitly name the super class:

在Python中,调用超类的__init__是可选的。如果您调用它,那么也可以选择是否使用超级标识符,或者是否显式地命名超类:

object.__init__(self)

In case of object, calling the super method is not strictly necessary, since the super method is empty. Same for __del__.

在对象的情况下,调用super方法并不是必需的,因为超级方法是空的。__del__相同。

OTOH, for __new__, you should indeed call the super method, and use its return as the newly-created object - unless you explicitly want to return something different.

对于__new__,您确实应该调用super方法,并使用它作为新创建的对象的返回——除非您明确地想要返回一些不同的东西。

#2


109  

If you need something from super's __init__ to be done in addition to what is being done in the current class's __init__, you must call it yourself, since that will not happen automatically. But if you don't need anything from super's __init__, no need to call it. Example:

如果您需要从super的__init__中得到一些东西,除了当前类的__init__中所做的之外,您必须自己调用它,因为这不会自动发生。但是如果你不需要任何超级的东西,就不用管它了。例子:

>>> class C(object):
    def __init__(self):
        self.b = 1


>>> class D(C):
    def __init__(self):
        super().__init__() # in Python 2 use super(D, self).__init__()
        self.a = 1


>>> class E(C):
    def __init__(self):
        self.a = 1


>>> d = D()
>>> d.a
1
>>> d.b  # This works because of the call to super's init
1
>>> e = E()
>>> e.a
1
>>> e.b  # This is going to fail since nothing in E initializes b...
Traceback (most recent call last):
  File "<pyshell#70>", line 1, in <module>
    e.b  # This is going to fail since nothing in E initializes b...
AttributeError: 'E' object has no attribute 'b'

__del__ is the same way, (but be wary of relying on __del__ for finalization - consider doing it via the with statement instead).

__del__是同样的方法,(但是要小心依赖于__del__来完成最后的定稿——考虑通过使用语句来完成它)。

I rarely use __new__. I do all the initialization in __init__.

我很少使用__new__。我在__init__中完成所有初始化。

#3


65  

In Anon's answer:
"If you need something from super's __init__ to be done in addition to what is being done in the current class's __init__ , you must call it yourself, since that will not happen automatically"

在Anon的回答中:“如果你需要从super的__init__中得到一些东西,除了在当前类的__init__中所做的事情之外,你必须自己调用它,因为这不会自动发生。”

It's incredible: he is wording exactly the contrary of the principle of inheritance.

令人难以置信的是:他的措辞恰好与继承原则正好相反。


It is not that "something from super's __init__ (...) will not happen automatically" , it is that it WOULD happen automatically, but it doesn't happen because the base-class' __init__ is overriden by the definition of the derived-clas __init__

这并不是说“超级的__init__(…)不会自动发生”,而是它会自动发生,但它不会发生,因为基类的__init__被定义为derived-clas __init__。

So then, WHY defining a derived_class' __init__ , since it overrides what is aimed at when someone resorts to inheritance ??

因此,为什么要定义一个derived_class的__init__,因为它覆盖了当某人使用继承时的目标?

It's because one needs to define something that is NOT done in the base-class' __init__ , and the only possibility to obtain that is to put its execution in a derived-class' __init__ function.
In other words, one needs something in base-class' __init__ in addition to what would be automatically done in the base-classe' __init__ if this latter wasn't overriden.
NOT the contrary.

因为我们需要定义在基类__init__中没有完成的事情,而获得这一功能的惟一可能是将其执行置于派生类的__init__函数中。换句话说,一个人在基础课程中需要一些东西,除了在基础课程中自动完成的内容之外,如果后者不是overriden的话。而不是相反。


Then, the problem is that the desired instructions present in the base-class' __init__ are no more activated at the moment of instantiation. In order to offset this inactivation, something special is required: calling explicitly the base-class' __init__ , in order to KEEP , NOT TO ADD, the initialization performed by the base-class' __init__ . That's exactly what is said in the official doc:

然后,问题是在基类__init__中显示的所需指令在实例化时不再被激活。为了抵消这种失活,需要一些特殊的东西:明确地调用基类的__init__,以便保持,而不是添加,由base类的__init__执行的初始化。这就是在官方文件中所说的:

An overriding method in a derived class may in fact want to extend rather than simply replace the base class method of the same name. There is a simple way to call the base class method directly: just call BaseClassName.methodname(self, arguments).
http://docs.python.org/tutorial/classes.html#inheritance

派生类中的重写方法实际上可能希望扩展而不是简单地替换相同名称的基类方法。有一种直接调用基类方法的简单方法:只调用BaseClassName。methodname(自我,参数)。http://docs.python.org/tutorial/classes.html继承

That's all the story:

这是所有的故事:

  • when the aim is to KEEP the initialization performed by the base-class, that is pure inheritance, nothing special is needed, one must just avoid to define an __init__ function in the derived class

    当目标是保持基类所执行的初始化时,这是纯继承,不需要什么特殊的东西,必须避免在派生类中定义__init__函数。

  • when the aim is to REPLACE the initialization performed by the base-class, __init__ must be defined in the derived-class

    当目标是替换base类执行的初始化时,__init__必须在derived类中定义。

  • when the aim is to ADD processes to the initialization performed by the base-class, a derived-class' __init__ must be defined , comprising an explicit call to the base-class __init__

    当目标是将进程添加到由base类执行的初始化时,必须定义一个derived类的__init__,其中包含对基类__init__的显式调用。


What I feel astonishing in the post of Anon is not only that he expresses the contrary of the inheritance theory, but that there have been 5 guys passing by that upvoted without turning a hair, and moreover there have been nobody to react in 2 years in a thread whose interesting subject must be read relatively often.

我觉得惊人后不久他不仅表达了相反的遗传理论,但这已经有5人路过upvoted毫不畏惧,而且已经有2年没有人反应在一个有趣的主题必须经常阅读相对的线程。

#4


17  

Edit: (after the code change)
There is no way for us to tell you whether you need or not to call your parent's __init__ (or any other function). Inheritance obviously would work without such call. It all depends on the logic of your code: for example, if all your __init__ is done in parent class, you can just skip child-class __init__ altogether.

编辑:(在代码更改之后)我们没有办法告诉您是否需要调用您父母的__init__(或任何其他函数)。显然,如果没有这样的召唤,继承权将会发挥作用。这完全取决于代码的逻辑:例如,如果所有的__init__都是在父类中完成的,那么您可以完全跳过子类__init__。

consider the following example:

考虑下面的例子:

>>> class A:
    def __init__(self, val):
        self.a = val


>>> class B(A):
    pass

>>> class C(A):
    def __init__(self, val):
        A.__init__(self, val)
        self.a += val


>>> A(4).a
4
>>> B(5).a
5
>>> C(6).a
12

#5


4  

There's no hard and fast rule. The documentation for a class should indicate whether subclasses should call the superclass method. Sometimes you want to completely replace superclass behaviour, and at other times augment it - i.e. call your own code before and/or after a superclass call.

没有硬性规定。类的文档应该指出子类是否应该调用超类方法。有时,您希望完全替换超类行为,而在其他时候则需要增加它——即在超类调用之前和/或之后调用自己的代码。

Update: The same basic logic applies to any method call. Constructors sometimes need special consideration (as they often set up state which determines behaviour) and destructors because they parallel constructors (e.g. in the allocation of resources, e.g. database connections). But the same might apply, say, to the render() method of a widget.

更新:同样的基本逻辑适用于任何方法调用。构造函数有时需要特殊的考虑(因为它们通常设置状态决定行为)和析构函数,因为它们是并行构造函数(例如,在资源分配中,例如数据库连接)。但是,对于小部件的render()方法,同样的方法也适用。

Further update: What's the OPP? Do you mean OOP? No - a subclass often needs to know something about the design of the superclass. Not the internal implementation details - but the basic contract that the superclass has with its clients (using classes). This does not violate OOP principles in any way. That's why protected is a valid concept in OOP in general (though not, of course, in Python).

进一步更新:OPP是什么?你是说OOP吗?不——子类通常需要了解超类的设计。不是内部实现细节,而是超类与客户端的基本契约(使用类)。这并不违反OOP原则。这就是为什么在OOP中保护是一个有效的概念(当然,当然不是在Python中)。

#6


3  

IMO, you should call it. If your superclass is object, you should not, but in other cases I think it is exceptional not to call it. As already answered by others, it is very convenient if your class doesn't even have to override __init__ itself, for example when it has no (additional) internal state to initialize.

IMO,你应该叫它。如果你的超类是对象,你不应该这样做,但在其他情况下,我认为不调用它是异常的。正如其他人已经回答的那样,如果您的类甚至不需要重写__init__本身,就非常方便,例如,当它没有(额外的)内部状态来初始化时。