如果一个类都是同一个类的父级,是否可以通过super()
调用另一个类的方法?
class A:
def a(self, x):
return x * 2
class B:
def b(self, x):
tmp = super().a(x) # <---
return tmp + 2
class C(A, B):
def c(self):
return super().b(20)
print(C().c())
结果:
AttributeError: 'super' object has no attribute 'a'
我认为这会行得通,因为C.mro()
是[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
(所以其中是A
),应该是被调用方的MRO。
答案 0 :(得分:5)
是的,但是不太像这样。
一个类的MRO是该类所有祖先的总订单,包括他们之间没有超类关系的祖先。 A
和B
的待遇不平等; A
在C
的MRO中排在第一位(必需,因为在类声明中A
被列为B
之前的基类),因此进行super
查找将在B
的MRO中的C
之后开始,并完全跳过A
。
要使b
方法的super
查找有效,必须将C
创建为class C(B, A): ...
。如果您实际上不希望使用super().whatever
的跳过跳过行为,则根据您的目标,您可能只想用self.whatever
替换所有这些super
调用。如果您确实希望跳过跳过,但是想要以一种A
和B
被对称对待的方式,您可能需要为此建立自己的机制。
答案 1 :(得分:2)
我相信您可以只使用alt.renderers.enable('Jupyterlab')
,它应该可以正常工作。使用tmp = self.a(x)
用于访问基类。在这里,您只需要一个实例变量。
答案 2 :(得分:1)
很难想象这种情况是您真正想做的。只能在同时是A
和B
实例的对象上调用这种方法。 @ user2357112给出了对该问题的严格正确答案,但是正如注释中所指出的那样,使用super()
的解决方案并不是一个好的设计。因此,如果这不是一个抽象的语言律师难题,而您(或其他有相同问题的人)正在编写真实的代码,我将给出答案。
如果C
是唯一将同时扩展A
和B
的类,那么您可以做的最简单的事情是在类{{1 }}。
否则,如果多个类可能同时扩展b
和C
,则可以为所有此类扩展声明一个“基”类,在其中放置A
方法,然后进行其他类从那里继承,而不是分别继承B
和b
:
A
通过这种方式,不是B
实例的class A:
def a(self, x):
return x * 2
class B:
pass
class A_and_B(A, B):
def b(self, x):
tmp = self.a(x)
return tmp + 2
class C(A_and_B):
def c(self):
return self.b(20)
实例将没有B
方法,这是可取的,因为不能在非实例中调用该方法仍然是A
的
上面的代码调用对象具有的b
的任何实现,可以由子类覆盖。如果您绝对必须调用A
的{{1}}类的实现,而不是它的某些替代版本,则可以直接调用a
:
A
这仍然是一个糟糕的设计,但还不及破解a
来在实际上不是超类的类上调用方法。