class A():
def __init__( self, x, y):
self.x = x
self.y = y
class B():
def __init__( self, z=0):
self.z = z
class AB(A,B):
def __init__( self, x, y, z=0):
?
如何使AB的构造函数使用正确的参数调用A和B的构造函数?
我试过
class AB(A,B):
def __init__( self, x, y, z=0):
A.__init__(x,y)
B.__init__(z)
但这给了我一个错误。
答案 0 :(得分:14)
其他答案建议将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
__init__
,然后调用B
,然后调用A
,然后调用object
。
我们来看看:
>>> ab = AB(1)
__init__ is called in AB
__init__ is called in B
__init__ is called in A
但是通过这个链的这些调用是由super
完成的。当我们输入super(AB, self)
时,它意味着:在AB
的{{1}}链__mro__
之后找到下一个课程。
然后我们应该在self
中调用super
,在B
之后查找链中的下一个类:B
。
使用super(B, self)
而不是手动调用super
等非常重要,因为它可能会在以后导致问题。 Read this for more info
所以,如果你坚持A.__init__(self,...)
,那就有问题了。类中的super
方法需要不同的参数。而且您无法确定__init__
将在这些类中调用方法的顺序。在创建课程时,顺序由C3 algorithm确定。在子类中,另一个类可能介于调用链之间。因此,super
中不能有不同的参数,因为在这种情况下,您将始终考虑所有继承链,以了解如何调用__init__
方法。
例如,考虑添加__init__
和C(A)
类以及它们的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
和b
个类的A
和B
个实例。然后可以通过参考AB
和self.a
使用与否授权取决于您的案例,而您的问题并不明确。但这可能是一个考虑的选择。
答案 1 :(得分:12)