如何从 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
继承自 A
和 B
(按此顺序),因此它会偏向 A
。也就是说,您示例中 class C
的 MRO 是 (C, A, B, object)
。如果你想让它总是去B
然后A
,然后简单地切换superclasses的顺序。
class C(B, A):
...
这是最好的解决方案。这是可以预见的,Python 程序员将立即理解此 class 中 super()
调用的意图。如果它符合您的需要,我推荐它。
但是,如果您有一个复杂的 multi-inheritance 系统并且需要访问 both A
和 B
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 方法,您可能会考虑重构您的代码以使用更少的多重继承。但是如果您真的需要它,这个功能就在那里。
我有 类 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
继承自 A
和 B
(按此顺序),因此它会偏向 A
。也就是说,您示例中 class C
的 MRO 是 (C, A, B, object)
。如果你想让它总是去B
然后A
,然后简单地切换superclasses的顺序。
class C(B, A):
...
这是最好的解决方案。这是可以预见的,Python 程序员将立即理解此 class 中 super()
调用的意图。如果它符合您的需要,我推荐它。
但是,如果您有一个复杂的 multi-inheritance 系统并且需要访问 both A
和 B
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 方法,您可能会考虑重构您的代码以使用更少的多重继承。但是如果您真的需要它,这个功能就在那里。