Python 调用多个父级时无法理解super()

Python 调用多个父级时无法理解super(),python,inheritance,constructor,super,Python,Inheritance,Constructor,Super,我一直在研究Python3(我的代码示例使用3.7.2)以及当一个类继承多个类时如何正确使用super() 我读过这个,还有这个,还有这个。我认为问题在于,SO链接是针对较旧版本的Python的,而本文是针对Python3的,但仍然令人困惑 假设我有以下代码(如果您认为可以更好地对关系建模,请不要担心,这只是一个示例来说明我的问题): Main: gun = Sniper("Standard Sniper", 10, 20, "small") gun.adjust_scope() print(

我一直在研究Python3(我的代码示例使用3.7.2)以及当一个类继承多个类时如何正确使用
super()

我读过这个,还有这个,还有这个。我认为问题在于,SO链接是针对较旧版本的Python的,而本文是针对Python3的,但仍然令人困惑

假设我有以下代码(如果您认为可以更好地对关系建模,请不要担心,这只是一个示例来说明我的问题):

Main:

gun = Sniper("Standard Sniper", 10, 20, "small")
gun.adjust_scope()

print(Sniper.__mro__)
以及
MRO

(<class 'inheritnacewithsuper.Sniper'>, 
 <class 'inheritnacewithsuper.Weapon'>, 
 <class 'inheritnacewithsuper.Reloadable'>, <class 'object'>)
(,
, 
, )
代码可以工作并调用所需的父类,但我想确保,在使用Python 3.7和
super()
时,使用的是
super()。\uuuu init\uuuu(name,damage)
super()。\uuu init\uuuu(self,amount)
,初始化父构造函数的正确方法

本文没有这样做,而是只为一个类调用了
super()
RightPyramid(正方形、三角形)

我只是想确保我在正确的轨道上,并使用正确的做法

super()
需要您的代码配合。你的
武器
可重新加载的
类没有,所以你实际上不想在这里使用
super()
。您可以直接在这些基类上调用未绑定的方法:

class Sniper(Weapon, Reloadable):
    def __init__(self, name, damage, amount, scope_type):
        Weapon.__init__(self, name, damage)
        Reloadable.__init__(self, amount)
        self.scope_type = scope_type
如果没有
super()
\uuuu init\uuuu
方法是未绑定的,因此需要显式地传入
self

有关如何以协作方式使用
super()
的详细概述,请参见Python核心开发人员Raymond Hettinger(或)

为了完全协作,层次结构中的所有类都应该在类链中传递
super()。()
调用。对于像
Reloadable
这样的混合类,您可能希望使用一个基本的不可操作类,或者在调用
super()时处理错误
,或将参数作为关键字参数传递,并使每个
方法接受任意关键字参数以再次传递:

class Weapon:
    def __init__(self, name, damage, **kwargs):
        self.name = name
        self.damage = damage
        # pass on any remaining arguments
        super().__init__(**kwargs)

class Reloadable:    
    def __init__(self, amount, **kwargs):
        self.amount = amount
        # pass on any remaining arguments
        super().__init__(**kwargs)

class Sniper(Weapon, Reloadable):    
    def __init__(self, name, damage, amount, scope_type):
        self.scope_type = scope_type
        super().__init__(name=name, damage=damage, amount=amount)

    def adjust_scope(self):
        print("Adjusting my scope")
super()
需要你的代码配合。你的
武器
可重新加载的
类不需要,因此你实际上不想在这里使用
super()
。你可以直接在这些基类上调用未绑定的方法:

class Sniper(Weapon, Reloadable):
    def __init__(self, name, damage, amount, scope_type):
        Weapon.__init__(self, name, damage)
        Reloadable.__init__(self, amount)
        self.scope_type = scope_type
如果没有
super()
\uuuu init\uuuu
方法是未绑定的,因此需要显式地传入
self

有关如何以协作方式使用
super()
的详细概述,请参见Python核心开发人员Raymond Hettinger(或)

为了完全协作,层次结构中的所有类都应该在类链中传递
super()。()
调用。对于像
Reloadable
这样的混合类,您可能希望使用一个基本的不可操作类,或者在调用
super()时处理错误
,或将参数作为关键字参数传递,并使每个
方法接受任意关键字参数以再次传递:

class Weapon:
    def __init__(self, name, damage, **kwargs):
        self.name = name
        self.damage = damage
        # pass on any remaining arguments
        super().__init__(**kwargs)

class Reloadable:    
    def __init__(self, amount, **kwargs):
        self.amount = amount
        # pass on any remaining arguments
        super().__init__(**kwargs)

class Sniper(Weapon, Reloadable):    
    def __init__(self, name, damage, amount, scope_type):
        self.scope_type = scope_type
        super().__init__(name=name, damage=damage, amount=amount)

    def adjust_scope(self):
        print("Adjusting my scope")

当您说不合作时,您的意思是使用
ABC
module?@EmilyScott:使用关键字参数使调用者和被调用者需要具有匹配的参数签名要求变得更容易;
**kwargs
捕获所有使每个
\u init\u
实现“容忍”传递链中的额外参数@EmilyScott:正如Raymond所写:一种更灵活的方法是让祖先树中的每个方法协同设计以接受关键字参数和关键字参数字典,删除它需要的任何参数,并使用
**kwds
转发剩余参数,最终让字典为最终ca清空ll在链中。@EmilyScott:
Sniper()
这里接受
name
damage
amount
作为明确命名的参数,因此我们需要将这些参数传递给基类,我们在这里通过将它们作为关键字参数传递来实现。@EmilyScott:至于跟踪PyCon:几乎每一次谈话都会被录制并放在YouTube上,通常在录制的几个小时内。查看给定年份的日程安排,选择您认为可能有趣的演讲,并在YouTube上查找。例如,查看,然后在您最喜欢的搜索引擎中插入一个带有“pycon 2018”的标题,它将引导您进入演讲。当您说不合作时,您的意思是使用
ABC
模块?@EmilyScott:使用关键字参数使调用者和被调用者需要一个匹配的参数签名要求变得容易得多;
**kwargs
catch all使每个
\uuuuu init\uuuuu
实现“容忍”在链上传递的额外参数。@EmilyScott:正如Raymond所写:一种更灵活的方法是让祖先树中的每个方法都协作ERATIVE设计用于接受关键字参数和关键字参数字典,删除它所需的任何参数,并使用
**kwds
转发其余参数,最终使字典为空,以供链中的最后调用。@EmilyScott:
Sniper()
这里接受
name
damage
amount
作为明确命名的参数,因此我们需要将这些参数传递给基类,我们在这里通过将它们作为关键字参数传递来实现。@EmilyScott:至于跟踪PyCon:几乎每一次谈话都会被录制并放在YouTube上,通常在录制的几个小时内。查看给定年份的日程安排,选择您认为可能感兴趣的演讲,并在YouTube上查找。例如,查看,然后在您最喜欢的搜索引擎中插入一个标题“pycon 2018”,它将引导您进入演讲。