【问题标题】:How Python's Super() works in multiple inheritance for superclasses?Python 的 Super() 如何在超类的多重继承中工作?
【发布时间】:2023-01-14 12:46:41
【问题描述】:

我试图了解 super 在 python 的超类多重继承中是如何工作的,例如在下面的代码中:

class First():
    def __init__(self, parm1, **kwargs):
        super().__init__(**kwargs)
        self.parm1 = parm1
        self.parm3 = 'one'


class Second():
    def __init__(self, parm2 = 'zero', **kwargs):
        super().__init__(**kwargs)
        self.parm2 = parm2

class Third(First,Second):
    def __init__(self,parm1):
        super().__init__(parm1=parm1)


trd = Third('tst')
print(trd.parm1)    # 'tst'
print(trd.parm3)    # 'one'
print(trd.parm2)    # 'zero'  

如果我删除 super().__init__(**kwargs) 执行结束

“第三”对象没有属性“parm2”

仅打印 parm1parm3,即使我在 Class Third(First,Second) 中声明了层次结构。

我知道所有类都继承自 Object 类,但我不明白它如何与父类中的 super() 类相关,以及后者如何允许访问第二个父类的属性。

【问题讨论】:

  • super()super(__class__, <first argument>)相同

标签: python python-3.x hierarchy multiple-inheritance super


【解决方案1】:

https://realpython.com/lessons/multiple-inheritance-python/

基类从左到右应用,即。最基类在右边。

例如在class Third(First,Second) 中来自First 的内容将覆盖来自Second 的内容。即Second 是这里最基类。 (从命名来看,你可能期望相反?)

我们也可以通过检查 Third 的“方法解析顺序”来看到这一点:

In [1]: Third.__mro__
Out[1]: (__main__.Third, __main__.First, __main__.Second, object)

我们可以按照从左到右的顺序将此元组读作子级->父级。见https://stackoverflow.com/a/2010732/202168

另外要知道的是super().__init__()会找一个不同的父类来调用视情况而定.

例如First 不继承自Second,因此如果您实例化一个Firstsuper 调用将直接转到object。我们可以在 MRO 中看到这一点:

In [2]: First.__mro__
Out[2]: (__main__.First, object)

但是当我们实例化Third时,该类继承自FirstSecond...所以super调用链将反映Third.__mro__...中的顺序,这意味着super调用First现在会调用Second中的方法(因为Second是下一个父类从发起super调用链的子类来看). super调用Second将调用object__init__,链结束的地方。

所有这一切意味着,如果您从First 中删除super().__init__(**kwargs),那么超级调用链在到达Second.__init__ 之前就会中断。

因此你得到了AttributeError“‘第三’对象没有属性‘parm2’”当你尝试print(trd.parm2)时。

【讨论】:

  • 好的,谢谢,所以如果我理解: - 覆盖的顺序是从类括号的右到左 - super().__init__(**kwargs) 就像是通过不同继承的“链接”,所以只有当有“水平”时才有必要遗产
  • super() 返回“下一个”父类(动态解析取决于哪个是最终实例化的“顶层”或子类)如果您希望您的方法在类层次结构中很好地发挥作用,它们通常应该使用super() 来在可能存在的任何父类上调用相同的方法。所以在 __init__ 方法的情况下,几乎总是需要的,因为所有类都有这样的方法(包括 object 根类型)
【解决方案2】:

object班级也有吗__init__()他们的方法?

【讨论】:

    猜你喜欢
    • 2018-01-27
    相关资源
    最近更新 更多