__init__() 应该调用父类的 __init__() 吗?
我在 Objective-C 中使用过这个构造:
- (void)init {
if (self = [super init]) {
// init class
}
return self;
}
Should Python also call theparent class'simplementation for __init__
?
class NewClass(SomeOtherClass):
def __init__(self):
SomeOtherClass.__init__(self)
# init class
对于 __new__()
和 __del__()
来说,这也是对/错吗?
编辑:有一个非常相似的问题:继承和覆盖Python 中的__init__
I'm used that in Objective-C I've got this construct:
- (void)init {
if (self = [super init]) {
// init class
}
return self;
}
Should Python also call the parent class's implementation for __init__
?
class NewClass(SomeOtherClass):
def __init__(self):
SomeOtherClass.__init__(self)
# init class
Is this also true/false for __new__()
and __del__()
?
Edit: There's a very similar question: Inheritance and Overriding __init__
in Python
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果除了当前类的
__init__ 中正在执行的操作之外,您还需要执行 super 的
您必须自己调用它,因为这不会自动发生。但如果您不需要 super 的 __init__ 中的任何内容,则无需调用它。示例:__init__
中的某些操作,__del__
的方式相同(但要小心依赖__del__
进行终结 - 考虑通过 with 语句来完成)。我很少使用 __new__。 我在 __init__ 中完成所有初始化。
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:__del__
is the same way, (but be wary of relying on__del__
for finalization - consider doing it via the with statement instead).I rarely use
__new__.
I do all the initialization in__init__.
在 Anon 的回答中:
“如果除了当前类的
__init__
中正在执行的操作之外,您还需要执行 super 的__init__
中的某些操作,则必须自己调用它,因为这会不会自动发生”令人难以置信:他的措辞与继承原则完全相反。
这并不是说“来自 super 的
__init__
(...) 的事情不会自动发生”,而是它会自动发生,但它不会发生这种情况是因为基类'__init__
被派生类__init__
的定义覆盖所以那么,为什么要定义派生类'
__init__
,因为它超越了某人诉诸继承时的目标?这是因为需要定义一些在基类 __init__ 中没有完成的东西,而获得它的唯一可能是将其执行放在派生类 __init__ 中代码> 函数。
换句话说,除了基类'
__init__
中自动执行的操作之外,还需要基类'__init__
中的某些内容,如果后者未被覆盖。并非相反。
然后,问题是基类'
__init__
中存在的所需指令在实例化时不再被激活。为了抵消这种失活,需要一些特殊的东西:显式调用基类的__init__
,以便 KEEP (而不是添加)由基类执行的初始化-class'__init__
。这正是官方文档中所说的:
这就是全部故事:
当目标是保持基类执行的初始化时,即纯继承,不需要任何特殊的东西,必须避免在中定义
__init__
函数派生类,
当目标是替换由基类执行的初始化时,
__init__
必须在派生类中定义必须定义 ,包括对基类
__init__
的显式调用,
Anon 的帖子让我感到惊讶的不仅仅是他表达了相反的内容继承理论,但已经有 5 个家伙路过,毫不犹豫地投了赞成票,而且两年来没有人在一个有趣的主题必须相对经常阅读的帖子中做出反应。
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"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__
So then, WHY defining a derived_class'
__init__
, since it overrides what is aimed at when someone resorts to inheritance ??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.
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:
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 classwhen the aim is to REPLACE the initialization performed by the base-class,
__init__
must be defined in the derived-classwhen 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__
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.
在 Python 中,调用超类的
__init__
是可选的。如果你调用它,那么是否使用 super 标识符,或者是否显式命名超类也是可选的:对于对象,调用 super 方法并不是绝对必要的,因为 super方法为空。与
__del__
相同。另一方面,对于 __new__ ,您确实应该调用 super 方法,并将其返回值用作新创建的对象 - 除非您明确希望返回不同的内容。
In Python, calling the super-class'
__init__
is optional. If you call it, it is then also optional whether to use thesuper
identifier, or whether to explicitly name the super class:In case of object, calling the super method is not strictly necessary, since the super method is empty. Same for
__del__
.On the other hand, 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.编辑:(代码更改后)
我们无法告诉您是否需要调用父级的
__init__
(或任何其他函数)。显然,如果没有这样的调用,继承也可以工作。这完全取决于代码的逻辑:例如,如果所有__init__
都在父类中完成,则可以完全跳过子类__init__
。考虑以下示例:
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.consider the following example:
没有硬性规定。类的文档应指示子类是否应调用超类方法。有时您希望完全替换超类行为,而有时则对其进行增强 - 即在超类调用之前和/或之后调用您自己的代码。
更新:相同的基本逻辑适用于任何方法调用。构造函数有时需要特殊考虑(因为它们经常设置决定行为的状态)和析构函数,因为它们与构造函数并行(例如在资源分配中,例如数据库连接)。但同样的情况也可能适用于小部件的 render() 方法。
进一步更新:什么是 OPP?你的意思是OOP吗?不 - 子类通常需要了解有关超类设计的一些。不是内部实现细节 - 而是超类与其客户(使用类)之间的基本契约。这并不以任何方式违反 OOP 原则。这就是为什么
protected
在一般的 OOP 中是一个有效的概念(当然,在 Python 中不是)。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.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).IMO,你应该称呼它。如果你的超类是
object
,你不应该,但在其他情况下我认为不调用它是例外。正如其他人已经回答的那样,如果您的类甚至不必重写 __init__ 本身,例如当它没有(额外的)内部状态要初始化时,这是非常方便的。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.是的,您应该始终显式调用基类
__init__
作为良好的编码实践。忘记这样做可能会导致微妙的问题或运行时错误。即使__init__
不带任何参数也是如此。这与其他语言不同,在其他语言中,编译器会隐式为您调用基类构造函数。 Python 不这样做!总是调用基类
_init__
的主要原因是基类通常会创建成员变量并将它们初始化为默认值。因此,如果您不调用基类 init,则不会执行任何代码,并且最终会得到没有成员变量的基类。示例:
这将打印..
运行此代码。
Yes, you should always call base class
__init__
explicitly as a good coding practice. Forgetting to do this can cause subtle issues or run time errors. This is true even if__init__
doesn't take any parameters. This is unlike other languages where compiler would implicitly call base class constructor for you. Python doesn't do that!The main reason for always calling base class
_init__
is that base class may typically create member variable and initialize them to defaults. So if you don't call base class init, none of that code would be executed and you would end up with base class that has no member variables.Example:
This prints..
Run this code.