同一类的另一个父级的调用方法

时间:2019-11-22 02:43:18

标签: python python-3.x

如果一个类都是同一个类的父级,是否可以通过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。

3 个答案:

答案 0 :(得分:5)

是的,但是不太像这样。

一个类的MRO是该类所有祖先的总订单,包括他们之间没有超类关系的祖先。 AB的待遇不平等; AC的MRO中排在第一位(必需,因为在类声明中A被列为B之前的基类),因此进行super查找将在B的MRO中的C之后开始,并完全跳过A

要使b方法的super查找有效,必须将C创建为class C(B, A): ...。如果您实际上不希望使用super().whatever的跳过跳过行为,则根据您的目标,您可能只想用self.whatever替换所有这些super调用。如果您确实希望跳过跳过,但是想要以一种AB被对称对待的方式,您可能需要为此建立自己的机制。

答案 1 :(得分:2)

我相信您可以只使用alt.renderers.enable('Jupyterlab'),它应该可以正常工作。使用tmp = self.a(x)用于访问基类。在这里,您只需要一个实例变量。

答案 2 :(得分:1)

很难想象这种情况是您真正想做的。只能在同时是AB实例的对象上调用这种方法。 @ user2357112给出了对该问题的严格正确答案,但是正如注释中所指出的那样,使用super()的解决方案并不是一个好的设计。因此,如果这不是一个抽象的语言律师难题,而您(或其他有相同问题的人)正在编写真实的代码,我将给出答案。


如果C是唯一将同时扩展AB的类,那么您可以做的最简单的事情是在类{{1 }}。

否则,如果多个类可能同时扩展bC,则可以为所有此类扩展声明一个“基”类,在其中放置A方法,然后进行其他类从那里继承,而不是分别继承Bb

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来在实际上不是超类的类上调用方法。