对于最基本的多重继承:
class A:
def __init__(self, a):
self.a = a
class B:
def __init__(self, b):
self.b = b
class C(A, B):
def __init__(self, a, b):
A.__init__(self, a)
B.__init__(self, b)
我不明白为什么要使用super()
。我想您可以用kwargs来实现它,但是肯定比上面的方法可读性差。我尚未在堆栈溢出中找到任何支持此方法的答案,但是对于这种情况,可以肯定它是最令人满意的吗?
在这个主题上有很多问题被标记为重复的问题,但是对于这种确切的情况没有令人满意的答案。 This question解决了多重继承问题,并将super()
用于钻石继承问题。在这种情况下,没有钻石继承,并且父类也没有彼此的知识,因此他们不需要像this那样调用super()
。
This answer处理super
的使用,但不像在此那样将参数传递给__init__
,而this answer处理传递的参数,但又是一个钻石继承。
答案 0 :(得分:1)
在这里使用super
的一种正确方法是
class A:
def __init__(self, a, **kwargs):
super().__init__(**kwargs)
self.a = a
class B:
def __init__(self, b, **kwargs):
super().__init__(**kwargs)
self.b = b
class C1(A, B):
pass
class C2(A, B):
def __init__(self, a, b, **kwargs):
super().__init__(a=a, b=b, **kwargs)
c1 = C1(a="foo", b="bar")
c2 = C2(a="foo", b="bar")
C
的方法解析顺序为[C, A, B, object]
。每次调用super()
时,它都会根据当时调用super()
的位置,返回MRO中 next 类的代理。
定义C
时有两个选择,这取决于是否要定义带有签名的C.__init__
签名,该签名提及初始化所需的两个参数A
和B
。对于C1
,C1.__init__
未定义,因此将调用A.__init__
。使用C2
,您需要显式调用链中的下一个__init__
方法。
C
知道它是A
和B
的子类,因此必须至少为已知的上游__init__
方法提供期望的参数。
A.__init__
会将所有 a
传递给下一类的__init__
方法。
B.__init__
将传递其所有 接收的内容,除了b
。
object.__init__
最终将被调用,并且假设所有先前的类都已正确删除了它们引入的关键字参数,则不会再收到其他参数。
更改各种__init__
的调用顺序意味着更改MRO,这意味着更改基类的顺序。如果您想要更多的控制权,那么协作多重继承不适合您。
答案 1 :(得分:0)
class A(object):
def __init__(self, *args, **kwargs):
super(A, self).__init__(*args, **kwargs)
self.a = kwargs['a']
class B(object):
def __init__(self, *args, **kwargs):
super(B, self).__init__()
self.b = kwargs['b']
class C(A, B):
def __init__(self, *args, **kwargs):
super(C, self).__init__(*args, **kwargs)
z = C(a=1,b=2)
z.b
2