为了账号安全,请及时绑定邮箱和手机立即绑定

具有 kwargs 的多重继承

具有 kwargs 的多重继承

大话西游666 2022-08-16 16:39:35
问题我在Dusty Phillips的面向对象编程中遇到了这个代码(为简洁起见进行了简化),我不确定这个定义的特定部分。class A:    def __init__(self, a, **kwargs):        super().__init__(**kwargs)        self.a = aclass B:    def __init__(self, b, **kwargs):        super().__init__(**kwargs)        self.b = bclass C(A, B):    def __init__(self, c, **kwargs):        super().__init__(**kwargs)        self.c = c问题由于方法解析顺序为 ,可以按以下方式定义吗?(__main__.C, __main__.A, __main__.B, object)class Bclass B:    def __init__(self, b):        self.b = b难道不是多余的,因为任何盈余传递到都会传递到,提高?super().__init__(**kwargs)class BkwargsCobjectTypeError:object.__init__() 只接受一个参数(要初始化的实例)这是否是如果被定义为而不是?Cclass C(B, A)class C(A, B)
查看完整描述

3 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

考虑如何实例化:C

c = C(a=3, b=5, c=9)

C.__init__获取所有关键字参数,但仅将关键字参数用于其自己的参数。其余的将传递给链中的下一个方法。在本例中,即 ,它“拉出”的参数并传递给 。 使用它并将(现在为空的)关键字参数集传递给下一个方法 。由于所有关键字参数都已“声明”并由其他类处理,因此会成功。c__init__A.__init__abB.__init__Bobject.__init__object.__init__

由于 MRO 的构造方式,正确使用的类保证在调用时集体为空。super()**kwargsobject.__init__


查看完整回答
反对 回复 2022-08-16
?
慕森王

TA贡献1777条经验 获得超3个赞

由于方法解析顺序为 ,可以按以下方式定义吗?(__main__.C, __main__.A, __main__.B, object)class B


否,因为这样会失败:


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)

的 MRO 是 ,所以必须调用,否则不会被调用。E(E, C, A, B, D, object)Bsuper().__init__D.__init__


难道不是多余的,因为任何盈余传递到都会传递到,提高?super().__init__(**kwargs)class BkwargsCobject


不,因为在上面的例子中,盈余将流向。但即使没有这个,当你调用一个参数太多构造函数时,引发错误也不是多余的;最好有一条错误消息通知您不正确的代码,而不是让错误未被发现。kwargsD.__init__


这是否是如果被定义为而不是?Cclass C(B, A)class C(A, B)


从某种意义上说,当然;但实际上,它是在任何类层次结构中发生的保护措施,只要层次结构中的其他类遵循相同的调用规则。Bsuper().__init__(**kwargs)


查看完整回答
反对 回复 2022-08-16
?
DIEA

TA贡献1820条经验 获得超2个赞

在这个例子中,如果它像你说的那样定义(第1点)并且是原样的(并且没有其他用途),那么它的工作原理是一样的。BC


至于第2点:如果还剩下关键字参数,那么对构造函数的调用确实会失败,例如:super()


c = C(a=1, b=2, c=3, d=4)

# -> TypeError: object.__init__() takes exactly one argument (the instance to initialize)

由于该类(最初)是编写的,因此如果像您所说的那样以相反的顺序使用,或者如果有一个(或)多个超类(es),也是可以的,例如:B


class D:

    def __init__(self, d, **kwargs):

        super().__init__(**kwargs)

        self.d = d


class C(A,B,D):

    ...


查看完整回答
反对 回复 2022-08-16
  • 3 回答
  • 0 关注
  • 121 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信