其他答案建议添加self
到第一个参数。
但通常会调用__init__
在父类中由super
.
考虑这个例子:
class A(object):
def __init__(self, x):
print('__init__ is called in A')
self.x = x
class B(object):
def __init__(self, *args, **kwargs):
print('__init__ is called in B')
super(B, self).__init__(*args, **kwargs)
class AB(B, A):
def __init__(self, *args, **kwargs):
print('__init__ is called in AB')
super(AB, self).__init__(*args, **kwargs)
AB
类包含构造函数和初始化器的调用顺序:
>>> AB.__mro__
(<class '__main__.AB'>, <class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
看,首先AB
's __init__
被调用,然后B
的,那么A
的,然后object
's.
让我们检查:
>>> ab = AB(1)
__init__ is called in AB
__init__ is called in B
__init__ is called in A
但是通过这条链的这些调用是由super
。当我们打字时super(AB, self)
,这意味着:找到然后下一堂课AB
in __mro__
链的self
.
然后我们应该调用super
in B
,在链中寻找下一个类B
: super(B, self)
.
使用很重要super
并且不手动调用A.__init__(self,...)
等等,因为这可能会导致以后出现问题。阅读本文以获取更多信息 https://fuhm.net/super-harmful.
所以,如果你坚持super
,那么就有问题了。__init__
类中的方法需要不同的参数。而且你无法确定其顺序super
将调用这些类中的方法。顺序由下式确定C3算法 http://www.python.org/download/releases/2.3/mro/在创建班级时。在子类中,另一个类可能会介于调用链之间。所以你不能有不同的参数__init__
,在这种情况下,您将始终考虑所有继承链以了解如何__init__
方法将被调用。
例如,考虑添加C(A)
and D(B)
类和CD
它们的子类。然后A
之后将不再被调用B
, 但是之后C
.
class A(object):
def __init__(self, *args, **kwargs):
print('__init__ is called in A')
super(A, self).__init__(*args, **kwargs)
class B(object):
def __init__(self, *args, **kwargs):
print('__init__ is called in B')
super(B, self).__init__(*args, **kwargs)
class AB(B,A):
def __init__(self, *args, **kwargs):
print('__init__ is called in AB')
super(AB, self).__init__(*args, **kwargs)
class C(A):
def __init__(self, *args, **kwargs):
print('__init__ is called in C')
super(C, self).__init__(*args, **kwargs)
class D(B):
def __init__(self, *args, **kwargs):
print('__init__ is called in D')
super(D, self).__init__(*args, **kwargs)
class CD(D,C):
def __init__(self, *args, **kwargs):
print('__init__ is called in CD')
super(CD, self).__init__(*args, **kwargs)
class ABCD(CD,AB):
def __init__(self, *args, **kwargs):
print('__init__ is called in ABCD')
super(ABCD, self).__init__(*args, **kwargs)
>>> abcd = ABCD()
__init__ is called in ABCD
__init__ is called in CD
__init__ is called in D
__init__ is called in AB
__init__ is called in B
__init__ is called in C
__init__ is called in A
所以我认为考虑使用是个好主意delegation
而不是这里的继承。
class AB(object):
def __init__(self, x, y, z=0):
self.a = A(x,y)
self.b = B(z)
所以,你只需创建a
and b
的实例A
and B
里面的课程AB
目的。然后可以根据需要通过参考的方法来使用它们self.a
and self.b
.
使用或不使用委托取决于您的情况,而您的问题尚不清楚。但这可能是一个值得考虑的选择。