kwargs 的多重继承
Multiple Inheritance with kwargs
问题
我在 面向对象编程 中遇到了这段代码 Dusty Phillips(为简洁起见进行了简化),我不确定其中的特定部分这个定义。
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 C(A, B):
def __init__(self, c, **kwargs):
super().__init__(**kwargs)
self.c = c
问题
- 既然方法解析顺序是
(__main__.C, __main__.A, __main__.B, object)
,那么class B
是否可以定义成下面的方式呢?
class B:
def __init__(self, b):
self.b = b
-
class B
中的 super().__init__(**kwargs)
是不是多余的,因为任何多余的 kwargs
传递给 C
都会传递给 object
,提高?
TypeError: object.__init__() takes exactly one argument (the instance to initialize)
- 如果
C
被定义为 class C(B, A)
而不是 class C(A, B)
,这是一种安全措施吗?
在这个例子中,如果 B
按照您所说的定义(第 1 点)并且 C
是原样(并且没有其他用途),那么它的工作原理是一样的。
至于第 2 点:调用 super()
的构造函数确实会失败,如果仍然有关键字参数,例如:
c = C(a=1, b=2, c=3, d=4)
# -> TypeError: object.__init__() takes exactly one argument (the instance to initialize)
因为class B
是(本来)写的,如果按照你说的倒序使用,或者有一个(或)多个超级class(es),例如:
class D:
def __init__(self, d, **kwargs):
super().__init__(**kwargs)
self.d = d
class C(A,B,D):
...
考虑如何实例化 C
:
c = C(a=3, b=5, c=9)
C.__init__
获取 所有 关键字参数,但仅将一个用于其自己的参数 c
。其余的传递给链中的下一个 __init__
方法。在本例中,即 A.__init__
,其中 "pulls out" 是 a
的参数,并将 b
传递给 B.__init__
。 B
使用它并将(现在为空的)关键字参数集传递给 next 方法 object.__init__
。因为所有关键字参数都已 "claimed" 并由其他 类 处理,所以 object.__init__
成功。
由于 MRO 的构建方式,正确使用 super()
的 类 保证 共同 **kwargs
届时将为空object.__init__
被调用。
Since the method resolution order is (__main__.C, __main__.A, __main__.B, object)
, could class B
be defined in the following way instead?
不,因为这样会失败:
class D:
def __init__(self, d, **kwargs):
self.d = d
super().__init__(**kwargs)
class E(C, D):
def __init__(self, e, **kwargs):
self.e = e
super().__init__(**kwargs)
E
的MRO是(E, C, A, B, D, object)
,所以B
必须调用super().__init__
否则D.__init__
不会被调用
Isn't super().__init__(**kwargs)
in class B
redundant, since any surplus kwargs
passed to C
will be passed to object
, raising?
不会,因为在上面的例子中,多余的kwargs
会转到D.__init__
。但即使没有它,当你调用带有太多参数的构造函数时引发错误也不是多余的;最好有一条错误消息通知您您的错误代码,而不是让错误未被发现。
Is this a safeguard for if C
was defined as class C(B, A)
instead of class C(A, B)
?
从某种意义上说,当然;但实际上它是对 any class 层次结构中发生的 B
的保护措施,只要层次结构中的其他 classes 遵循相同的规则呼叫 super().__init__(**kwargs)
.
问题
我在 面向对象编程 中遇到了这段代码 Dusty Phillips(为简洁起见进行了简化),我不确定其中的特定部分这个定义。
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 C(A, B):
def __init__(self, c, **kwargs):
super().__init__(**kwargs)
self.c = c
问题
- 既然方法解析顺序是
(__main__.C, __main__.A, __main__.B, object)
,那么class B
是否可以定义成下面的方式呢?
class B:
def __init__(self, b):
self.b = b
-
class B
中的super().__init__(**kwargs)
是不是多余的,因为任何多余的kwargs
传递给C
都会传递给object
,提高?
TypeError: object.__init__() takes exactly one argument (the instance to initialize)
- 如果
C
被定义为class C(B, A)
而不是class C(A, B)
,这是一种安全措施吗?
在这个例子中,如果 B
按照您所说的定义(第 1 点)并且 C
是原样(并且没有其他用途),那么它的工作原理是一样的。
至于第 2 点:调用 super()
的构造函数确实会失败,如果仍然有关键字参数,例如:
c = C(a=1, b=2, c=3, d=4)
# -> TypeError: object.__init__() takes exactly one argument (the instance to initialize)
因为class B
是(本来)写的,如果按照你说的倒序使用,或者有一个(或)多个超级class(es),例如:
class D:
def __init__(self, d, **kwargs):
super().__init__(**kwargs)
self.d = d
class C(A,B,D):
...
考虑如何实例化 C
:
c = C(a=3, b=5, c=9)
C.__init__
获取 所有 关键字参数,但仅将一个用于其自己的参数 c
。其余的传递给链中的下一个 __init__
方法。在本例中,即 A.__init__
,其中 "pulls out" 是 a
的参数,并将 b
传递给 B.__init__
。 B
使用它并将(现在为空的)关键字参数集传递给 next 方法 object.__init__
。因为所有关键字参数都已 "claimed" 并由其他 类 处理,所以 object.__init__
成功。
由于 MRO 的构建方式,正确使用 super()
的 类 保证 共同 **kwargs
届时将为空object.__init__
被调用。
Since the method resolution order is
(__main__.C, __main__.A, __main__.B, object)
, couldclass B
be defined in the following way instead?
不,因为这样会失败:
class D:
def __init__(self, d, **kwargs):
self.d = d
super().__init__(**kwargs)
class E(C, D):
def __init__(self, e, **kwargs):
self.e = e
super().__init__(**kwargs)
E
的MRO是(E, C, A, B, D, object)
,所以B
必须调用super().__init__
否则D.__init__
不会被调用
Isn't
super().__init__(**kwargs)
inclass B
redundant, since any surpluskwargs
passed toC
will be passed toobject
, raising?
不会,因为在上面的例子中,多余的kwargs
会转到D.__init__
。但即使没有它,当你调用带有太多参数的构造函数时引发错误也不是多余的;最好有一条错误消息通知您您的错误代码,而不是让错误未被发现。
Is this a safeguard for if
C
was defined asclass C(B, A)
instead ofclass C(A, B)
?
从某种意义上说,当然;但实际上它是对 any class 层次结构中发生的 B
的保护措施,只要层次结构中的其他 classes 遵循相同的规则呼叫 super().__init__(**kwargs)
.