这绝对是使用 super 的情况。您可以使用 *args 和 **kwargs 控制每个级别上的参数分派方式。需要注意的是,类声明中基类的顺序控制了 super 在查找下一个方法时搜索类的顺序。因此,它还将控制位置参数被消耗的顺序。
例如:
class A:
def __init__(self, a, *, caller):
print("A.__init__(a={!r}) called by {}".format(a, caller))
class B(A):
def __init__(self, b, *args, caller, **kwargs):
super().__init__(caller="B", *args, **kwargs )
print("B.__init__(b={!r}) called by {}".format(b, caller))
class C(A):
def __init__(self, c, *args, caller, **kwargs):
super().__init__(caller="C", *args, **kwargs)
print("C.__init__(c={!r}) called by {}".format(c, caller))
class D(B, C):
def __init__(self, d, *args, **kwargs):
super().__init__(caller="D", *args, **kwargs)
print("D.__init__(d={!r}) called by {}".format(d, "user"))
try:
print("too many arguments")
D(a=1, b=2, c=3, d=4, e=5)
except TypeError as e:
print(e)
try:
print("too few arguments")
D(a=1, c=3, d=4)
except TypeError as e:
print(e)
print("using keyword args")
D(a=1, b=2, c=3, d=4)
print("using positional args")
D(4, 2, 3, 1)
print("using a mix of positional and keyword args")
D(4, 2, a=1, c=3)
其输出结果为:
too many arguments
__init__() got an unexpected keyword argument 'e'
too few arguments
__init__() missing 1 required positional argument: 'b'
using keyword args
A.__init__(a=1) called by C
C.__init__(c=3) called by B
B.__init__(b=2) called by D
D.__init__(d=4) called by user
using positional args
A.__init__(a=1) called by C
C.__init__(c=3) called by B
B.__init__(b=2) called by D
D.__init__(d=4) called by user
using a mix of positional and keyword args
A.__init__(a=1) called by C
C.__init__(c=3) called by B
B.__init__(b=2) called by D
D.__init__(d=4) called by user
如果您不确定基类搜索的顺序,请使用D.mro()
。 mro
代表方法解析顺序。 它返回一个类列表,其中属性(在我们的情况下是__init__
)将被搜索。
>>> print(D.mro())
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>,
<class 'object'>]
*args, **kwargs
,提取每个类需要的参数,并将其余部分传递给super。 - Daniel Roseman*args
和**kwargs
是个好主意,但说实话,使用super
有点让我感到害怕,因为我并没有深入理解它的真正行为。 - Niourfsuper()
不要求所调用的方法具有相同的签名。 - martineauA
将是旧式类,因为它没有明确地派生自object
- 新式类具有不同的MRO(方法解析顺序)。 - martineau