给定以下类别A
、B
和C
:
class A:
def __init__(self, a, aa, aaa):
self.a = a
self.aa = aa
self.aaa = aaa
class B:
def __init__(self, b, bb, bbb):
self.b = b
self.bb = bb
self.bbb = bbb
class C(A, B):
def __init__(self, **kwargs):
super(C, self).__init__(**kwargs)
我想避免重复C
定义中的所有超类参数a
、aa
、aaa
、b
、bb
、bbb
:
class C(A, B):
def __init__(self, a, aa, aaa, b, bb, bbb):
super(C, self).__init__(**kwargs)
并以某种方式传递A
和B
Kwargs以在super().__init__
调用中解析,但使用我所描述的方式是不可能的,这将导致错误:
>>> c = C(a=1, aa=2, aaa=3, b=4, bb=5, bbb=6)
TypeError: A.__init__() got an unexpected keyword argument 'b'
正确的方法是调用A.__init__(self, **a_kwargs)
和B.__init__(self, **b_kwargs)
,但正如我所说,这会创建我试图避免的冗余参数。有没有更好的方法来实现同样的目标?
您可以这样做:
class A:
def __init__(self, a, aa, aaa, **kwargs):
self.a = a
self.aa = aa
self.aaa = aaa
super().__init__(**kwargs)
class B:
def __init__(self, b, bb, bbb, **kwargs):
self.b = b
self.bb = bb
self.bbb = bbb
super().__init__(**kwargs)
class C(A, B):
pass
c = C(a=1, aa=2, aaa=3, b=4, bb=5, bbb=6)
由于C
的MRO是[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
,因此A
将消耗其参数,并将其余参数传递给B
。
- 如果您也需要传递位置参数,您可以将其更改为:
class A:
def __init__(self, a, aa, aaa, *args, **kwargs):
self.a = a
self.aa = aa
self.aaa = aaa
super().__init__(*args, **kwargs)
class B:
def __init__(self, b, bb, bbb, *args, **kwargs):
self.b = b
self.bb = bb
self.bbb = bbb
super().__init__(*args, **kwargs)
class C(A, B):
pass
您可以使用内置的signature(callable)
函数来获得每个__init__
所需的关键字参数,并只传递函数所需的参数。这是否是一个好的设计,这是另一个讨论的问题。
from inspect import signature
class A:
def __init__(self, a, aa, aaa):
self.a = a
self.aa = aa
self.aaa = aaa
print(f"A obj: {a=}, {aa=}, {aaa=}")
class B:
def __init__(self, b, bb, bbb):
self.b = b
self.bb = bb
self.bbb = bbb
print(f"B obj: {b=}, {bb=}, {bbb=}")
class C(A, B):
def __init__(self, **kwargs):
A_params = {k:v for k, v in kwargs.items() if k in signature(A.__init__).parameters.keys()}
A.__init__(self, **A_params)
B_params = {k:v for k, v in kwargs.items() if k in signature(B.__init__).parameters.keys()}
B.__init__(self, **B_params)
c = C(a=1, aa=2, aaa=3, b=4, bb=5, bbb=6)
输出:
A obj: a=1, aa=2, aaa=3
B obj: b=4, bb=5, bbb=6