我最近发现(通过 StackOverflow)调用基类中的方法,我应该调用:
super([[derived class]], self).[[base class method]]()
没关系,它有效。但是,当我进行更改时,我发现自己经常在类之间复制和粘贴,并且经常忘记将派生类参数修复为 super() 函数。
我想避免必须记住更改派生类参数。我可以改为使用self.__class__super() 函数的第一个参数吗?
它似乎有效,但有充分的理由为什么我不应该这样做?
我最近发现(通过 StackOverflow)调用基类中的方法,我应该调用:
super([[derived class]], self).[[base class method]]()
没关系,它有效。但是,当我进行更改时,我发现自己经常在类之间复制和粘贴,并且经常忘记将派生类参数修复为 super() 函数。
我想避免必须记住更改派生类参数。我可以改为使用self.__class__super() 函数的第一个参数吗?
它似乎有效,但有充分的理由为什么我不应该这样做?
你不能。调用需要知道该super()方法属于哪个类,以便在基类中搜索覆盖的方法。
如果你传入self.__class__(或者更好的是type(self)),那么搜索方法的起始点super()是错误的,最终会再次调用它自己的方法。
将其视为形成方法解析顺序序列的类列表中的指针。如果您传入,type(self)则指针将引用任何子类而不是原始起点。
以下代码导致无限递归错误:
class Base(object):
    def method(self):
        print 'original'
class Derived(Base):
    def method(self):
        print 'derived'
        super(type(self), self).method()
class Subclass(Derived):
    def method(self):
        print 'subclass of derived'
        super(Subclass, self).method()
演示:
>>> Subclass().method()
subclass of derived
derived
derived
derived
<... *many* lines removed ...>
  File "<stdin>", line 4, in method
  File "<stdin>", line 4, in method
  File "<stdin>", line 4, in method
RuntimeError: maximum recursion depth exceeded while calling a Python object
因为type(self)是Subclass,不是 Derived,在Derived.method()。
在示例中,MROSubclass是[Subclass, Derived, Base],并且super()需要知道从哪里开始搜索任何被覆盖的方法。通过使用type(self)你告诉它从 开始Subclass,所以它会找到Derived.method()下一个,这就是我们开始的地方。
self.__class__可能不是子类,而是孙子或更年轻的类,从而导致堆栈中断循环。