Ale*_*ber 15 python inheritance constructor arguments
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):
?
Run Code Online (Sandbox Code Playgroud)
如何使AB的构造函数使用适当的参数调用A和B的构造函数?
我试过了
class AB(A,B):
def __init__( self, x, y, z=0):
A.__init__(x,y)
B.__init__(z)
Run Code Online (Sandbox Code Playgroud)
但这给了我一个错误.
ovg*_*vin 15
其他答案建议添加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)
Run Code Online (Sandbox Code Playgroud)
AB class包含应该调用构造函数和初始化器的顺序:
>>> AB.__mro__
(<class '__main__.AB'>, <class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
Run Code Online (Sandbox Code Playgroud)
看,这就是第一AB的__init__调用,那么B的,那么A的,然后object的.
让我们检查:
>>> ab = AB(1)
__init__ is called in AB
__init__ is called in B
__init__ is called in A
Run Code Online (Sandbox Code Playgroud)
但通过这个链条的这些调用是由super.当我们输入时super(AB, self),它意味着:AB在__mro__链中找到下一个类self.
那么,我们应该调用super的B,寻找后链中的下一类B:super(B, self).
使用super而不是手动调用A.__init__(self,...)等很重要,因为它可能会导致以后出现问题.阅读本文以获取更多信息.
所以,如果你坚持下去super,那就有问题了.__init__类中的方法需要不同的参数.并且您无法确定super将在这些类中调用方法的顺序.顺序由类算法创建时的C3算法确定.在子类中,另一个类可能介于调用链之间.因此,您不能拥有不同的参数__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
Run Code Online (Sandbox Code Playgroud)
所以我认为delegation在这里考虑使用而不是继承是个好主意.
class AB(object):
def __init__(self, x, y, z=0):
self.a = A(x,y)
self.b = B(z)
Run Code Online (Sandbox Code Playgroud)
因此,您只需在对象内创建a和b实例A和B类AB.然后可以通过参考self.a和方法通过方法使用它们self.b.
使用与否授权取决于您的案例,而您的问题并不明确.但它可能是一个考虑的选择.
use*_*ica 13
你没有通过self.
class AB(A, B):
def __init__(self, x, y, z=0):
A.__init__(self, x, y)
B.__init__(self, z)
Run Code Online (Sandbox Code Playgroud)
请注意,如果此继承层次结构变得更复杂,则会遇到构造函数未执行或重新执行的问题.考虑super(和问题与super),不要忘记要继承object如果你在2.x和你的类不从别的继承.