如何从 Python 中的子 class 调用间接父 class 的方法?

How do I call an indirect parent class's method from a child class in Python?

我有 类 A、B 和 C。C 继承自 A 和 B,并且在大多数情况下,只要有方法相互覆盖,我就希望 A 覆盖 B,所以我有以下结构:

class A:
    def some_method(self):
        return self.some_attribute

class B:
    def some_method(self):
        return self.some_other_attribute

class C(A,B):
    def some_method(self):
        var = super().some_method() -> this will give me the method from A, but I want the B one
        return var + 1

所以我的问题是如何使用 super() 或其他方式从 B 调用 some_method(),以便我可以在 C 的方法覆盖中使用它?

另外为了记录我正在使用 Python 3.*

Python是一种多重继承的语言,也就是说一个class可以有多个直接超class。但是为了调用 super(),Python 总是 线性化 继承层次结构以确定谁是“最佳” superclass。这称为 method resolution order,通过 Python.

中的 __mro__ 变量访问

所以如果我们有 class 层次结构

class A(object): pass
class B(A): pass
class C(A): pass
class D(B, C): pass

那么虽然D有两个超classses,如果我们在D中说super(),它只会给我们B。那是因为 D 的 MRO 为我们创建了一个线性层次结构。在 Python 3 中,它使用了一种称为 C3 resolution 的算法,它为我们提供了这个层次结构

>>> D.__mro__
(<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)

因此,如果我们在 class D 的方法中调用 super(),我们将获得 B 的版本,如果我们调用 super() 从那里,我们将获得 C 版本,然后是 A 版本,最后是 object 版本。

因此,在您的情况下,C 继承自 AB(按此顺序),因此它会偏向 A。也就是说,您示例中 class C 的 MRO 是 (C, A, B, object)。如果你想让它总是B然后A,然后简单地切换superclasses的顺序。

class C(B, A):
  ...

这是最好的解决方案。这是可以预见的,Python 程序员将立即理解此 class 中 super() 调用的意图。如果它符合您的需要,我推荐它。

但是,如果您有一个复杂的 multi-inheritance 系统并且需要访问 both AB superclasses,您始终可以直接使用 class 名称调用它们,完全放弃 super() 调用。

class C(B, A):
  def some_method(self):
    A.some_method(self) # Calls A's version on self
    B.some_method(self) # Calls B's version on self

如果 some_method 需要一些参数,您可以在明确的 self 参数之后传递它们。这会引起更多人的注意,因此如果您发现自己需要以复杂的方式访问两个不同的 superclass 方法,您可能会考虑重构您的代码以使用更少的多重继承。但是如果您真的需要它,这个功能就在那里。