问题:__init __()是否应该调用父类的__init __()?
我在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__()
吗?
编辑:有一个非常类似的问题:Python中的继承和重写__init__
回答 0
在Python中,调用超类__init__
是可选的。如果调用它,那么使用super
标识符还是显式命名超类也是可选的:
object.__init__(self)
对于对象,由于super方法为空,因此不必严格要求调用super方法。相同__del__
。
另一方面,对于__new__
,您确实应该调用super方法,并将其return用作新创建的对象-除非您明确希望返回其他内容。
回答 1
如果__init__
除了在当前类中正在执行的操作之外,还需要从super 进行操作,则__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__.
回答 2
在Anon的回答中:
“如果__init__
除了在当前类中所做的事情之外,还需要从super 进行一些事情__init__
,则必须自己调用它,因为这不会自动发生”
令人难以置信:他的措辞与继承原则完全相反。
不是说“ super __init__
(…)中的某事不会自动发生”,而是它会自动发生,但不会发生,因为__init__
派生类的定义覆盖了基类。__init__
那么,为什么要定义一个named_class’ __init__
,因为它会覆盖有人诉诸继承时的目标?
这是因为需要定义一些在基类中未完成的事情__init__
,而获得该结果的唯一可能性是将其执行置于派生类的__init__
函数中。
换句话说,如果在基类__init__
中__init__
没有被覆盖,除了在基类中会自动完成的事情外,还需要在基类中做些什么。
并非相反。
然后,问题是__init__
在实例化时不再激活存在于基类中的所需指令。为了抵消这种失活,需要做一些特殊的事情:显式调用基类’ __init__
,以便保留基类执行的初始化,而不是添加__init__
。这就是官方文档中所说的:
实际上,派生类中的重写方法可能想扩展而不是简单地替换相同名称的基类方法。有一种直接调用基类方法的简单方法:只需调用BaseClassName.methodname(self,arguments)。
http://docs.python.org/tutorial/classes.html#inheritance
这就是全部故事:
当目标是保留基类执行的初始化(即纯继承)时,不需要任何特殊操作,必须避免
__init__
在派生类中定义一个函数当目的是替换由基类执行的初始化时,
__init__
必须在派生类中定义当目标是将过程添加到由基类执行的初始化时,
__init__
必须定义一个派生类,包括对基类的显式调用__init__
在Anon的职位上,我感到惊讶的不仅是他表达了与继承理论相反的事实,而且还有5个人绕过那个被推崇而又不掉头的家伙,而且在过去的2年中,没有人反应一个线程,其有趣的主题必须相对频繁地阅读。
回答 3
编辑:(在代码更改之后)
我们无法告诉您是否需要调用父母的__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
没有硬性规定。类的文档应指出子类是否应调用超类方法。有时您想完全替换超类行为,而有时又要增强它-即在超类调用之前和/或之后调用您自己的代码。
更新:相同的基本逻辑适用于任何方法调用。构造函数有时需要特别考虑(因为它们经常设置确定行为的状态)和析构函数,因为它们并行构造函数(例如,在资源分配(例如数据库连接)中)。但是,对于render()
小部件的方法可能也是如此。
进一步更新:什么是OPP?你是说OOP吗?否-一个子类经常需要知道一些关于超类的设计。不是内部实现细节-而是超类与其客户(使用类)所拥有的基本契约。这丝毫不违反OOP原则。这就是为什么protected
在OOP中通常是一个有效的概念的原因(尽管在Python中当然不是)。
回答 5
海事组织,你应该给它打电话。如果您的超类是object
,则不应这样做,但在其他情况下,我认为不调用它是一种exceptions。正如其他人已经回答的那样,如果您的类甚至不必重写__init__
自身,例如在没有(其他)内部状态要初始化的情况下,这将非常方便。
回答 6
是的,您应该始终__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