我在Objective-C中使用它我有这个结构:
- (void)init {
if (self = [super init]) {
// init class
}
return self;
}
Python是否也应该为__init__
调用父类的实现?
class NewClass(SomeOtherClass):
def __init__(self):
SomeOtherClass.__init__(self)
# init class
对于__new__()
和__del__()
,这也是真/假吗?
修改:有一个非常相似的问题:Inheritance and Overriding __init__
in Python
答案 0 :(得分:125)
除了当前班级__init__
中的内容之外,如果你需要超级__init__,
的内容,你必须自己调用它,因为这不会自动发生。但是,如果你不需要来自super __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__
的方式相同,(但要谨慎依赖__del__
进行最终确定 - 请考虑通过with语句来实现)。
我很少使用__new__.
我在__init__.
答案 1 :(得分:83)
在Anon的回答中:
“如果除了当前班级__init__
中的内容之外,你需要完成超级__init__
的某些内容,你必须自己调用它,因为这不会自动发生”
令人难以置信的是:他的措辞完全与继承原则相反。
不是“来自超级__init__
(...)的东西不会自动发生”,它会自动发生,但它不会发生,因为基类'__init__
被derived-clas的定义覆盖__init__
那么,为什么定义一个derived_class'__init__
,因为它会覆盖当某人诉诸继承时的目标?
这是因为需要定义一些未在基类“__init__
中完成的东西,并且获得它的唯一可能性是将其执行放在派生类”__init__
函数中。
换句话说,一个人需要在基类“__init__
”中添加的内容,如果后者未被覆盖,则需要在base-classe'__init__
中自动完成。 。
不相反。
然后,问题是基类“__init__
中存在的所需指令在实例化时不再被激活。为了抵消这种失活,需要一些特殊的东西:明确调用基类“__init__
,以便 KEEP ,而不是添加,由基类执行的初始化” __init__
。
这正是官方文件中所说的:
派生类中的重写方法实际上可能需要扩展 而不是简单地替换相同名称的基类方法。 有一种简单的方法可以直接调用基类方法:只是 调用BaseClassName.methodname(self,arguments)。
http://docs.python.org/tutorial/classes.html#inheritance
这就是故事:
当目标是保持基类执行的初始化,即纯继承时,不需要特殊的东西,必须避免在派生类中定义__init__
函数
当目标是更新基类执行的初始化时,必须在派生类中定义__init__
当目标是将进程添加到基类执行的初始化时,必须定义派生类'__init__
,包括对基类{{1}的显式调用}
我在Anon的帖子中感到惊讶的不仅仅在于他表达了与继承理论相反的观点,而且还有5个人在没有转过头发的情况下匆匆过去,而且还没有人能够做出反应2年线程必须经常阅读其有趣的主题。
答案 2 :(得分:59)
在Python中,调用超类“__init__
是可选的。如果你调用它,那么它是否也可以选择使用super
标识符,还是显式命名超类:
object.__init__(self)
对于object,调用super方法并不是绝对必要的,因为super方法是空的。与__del__
相同。
另一方面,对于__new__
,你应该确实调用super方法,并将其返回作为新创建的对象 - 除非你明确想要返回不同的东西。
答案 3 :(得分:18)
修改 :(代码更改后)
我们无法告诉您是否需要致电您父母的__init__
(或任何其他功能)。如果没有这样的召唤,遗传显然会有效。这完全取决于代码的逻辑:例如,如果您的所有__init__
都在父类中完成,那么您可以完全跳过子类__init__
。
考虑以下示例:
>>> 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
答案 4 :(得分:4)
没有硬性规定。类的文档应该指示子类是否应该调用超类方法。有时你想要完全取代超类行为,并在其他时候增加它 - 即在超类调用之前和/或之后调用你自己的代码。
更新:相同的基本逻辑适用于任何方法调用。构造函数有时需要特别考虑(因为它们经常设置确定行为的状态)和析构函数,因为它们是并行构造函数(例如在资源分配中,例如数据库连接)。但是,相同的情况可能适用于小部件的render()
方法。
进一步更新:什么是OPP?你的意思是OOP?不 - 一个子类经常需要知道关于超类设计的某些东西。不是内部实现细节 - 而是超类与其客户端(使用类)的基本合同。这不会以任何方式违反OOP原则。这就是为什么protected
在OOP中是一个有效的概念(当然不是在Python中)。
答案 5 :(得分:4)
IMO,你应该打电话给它。如果您的超类是object
,那么您不应该,但在其他情况下,我认为不应该调用它。正如其他人已经回答的那样,如果你的类甚至不必覆盖__init__
本身,例如当它没有(额外的)内部状态来初始化时,这是非常方便的。
答案 6 :(得分:1)
是的,您应该始终显式调用基类__init__
作为一种良好的编码习惯。忘记执行此操作可能会导致细微的问题或运行时错误。即使__init__
不带任何参数也是如此。这与其他语言不同,在其他语言中,编译器会为您隐式调用基类构造函数。 Python不会那样做!
始终调用基类_init__
的主要原因是基类通常可以创建成员变量并将其初始化为默认值。因此,如果不调用基类init,则不会执行任何代码,并且最终会得到没有成员变量的基类。
示例:
class Base:
def __init__(self):
print('base init')
class Derived1(Base):
def __init__(self):
print('derived1 init')
class Derived2(Base):
def __init__(self):
super(Derived2, self).__init__()
print('derived2 init')
print('Creating Derived1...')
d1 = Derived1()
print('Creating Derived2...')
d2 = Derived2()
此打印。.
Creating Derived1...
derived1 init
Creating Derived2...
base init
derived2 init