我有三个班级:A
,B
和C
。
C
继承自A
和B
(按此顺序)。 A
和B
的构造函数签名不同。如何调用两个父类的__init__
方法?
我在代码中的努力:
class A(object):
def __init__(self, a, b):
super(A, self).__init__()
print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b)))
class B(object):
def __init__(self, q):
super(B, self).__init__()
print('Init {} with arguments {}'.format(self.__class__.__name__, (q)))
class C(A, B):
def __init__(self):
super(A, self).__init__(1, 2)
super(B, self).__init__(3)
c = C()
产生错误:
Traceback (most recent call last):
File "test.py", line 16, in <module>
c = C()
File "test.py", line 13, in __init__
super(A, self).__init__(1, 2)
TypeError: __init__() takes 2 positional arguments but 3 were given
我发现this resource解释了使用不同参数集的多重继承,但他们建议使用*args
和**kwargs
来用于所有参数。我认为这非常难看,因为我无法从子类中的构造函数调用中看到我传递给父类的哪种参数。
答案 0 :(得分:67)
不使用super(baseclass, ...)
,除非您知道自己在做什么。 super()
的第一个参数告诉它在查找下一个要使用的方法时跳过的类。例如。 super(A, ...)
会查看MRO,找到A
,然后开始在下一个基类上查找__init__
,不 {{1本身。对于A
,MRO为C
,因此(C, A, B, object)
会找到super(A, self).__init__
。
对于这些情况,您不希望使用合作继承,而是直接引用B.__init__
和A.__init__
。只有在您调用的方法具有相同签名或将使用B.__init__
和super()
吞下不受支持的参数时,才应使用*args
。在这种情况下,只需要进行一次**vargs
调用,并且MRO命令中的下一个类将负责处理呼叫。
换句话说:当你使用super(C, self).__init__()
时,你无法知道MRO中接下来会是什么类,所以这个类更好地支持你传递给它的参数。如果不是这种情况,请不使用super()
。
直接调用基本super()
方法:
__init__
使用合作class A(object):
def __init__(self, a, b):
print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b)))
class B(object):
def __init__(self, q):
print('Init {} with arguments {}'.format(self.__class__.__name__, (q)))
class C(A, B):
def __init__(self):
# Unbound functions, so pass in self explicitly
A.__init__(self, 1, 2)
B.__init__(self, 3)
:
super()