当在派生类中调用super()时,我可以传入self .__ class__吗?

我最近发现(通过StackOverflow),要调用基类中的方法,我应该调用:

super([[derived class]], self).[[base class method]]()

这很好,它工作。 然而,当我做出改变时,我发现自己经常在类之间复制和粘贴,并且经常忘记修改派生类参数到super()函数。

我想避免不得不记得改变派生类的参数。 我可以改为使用self.__class__作为super()函数的第一个参数吗?

这似乎工作,但有没有很好的理由,为什么我不应该这样做?

你不能。 super()调用需要知道该方法是什么类的一部分,以search基类重写的方法。

如果你传入self.__class__ (或者更好的是, type(self) ),那么super()被赋予错误的起点来search方法,并且最终会再次调用它自己的方法

将其看作构成方法parsing顺序序列的类列表中的一个指针。 如果你传入type(self)那么指针将引用任何子类而不是原始的起始点。

下面的代码导致无限的recursion错误:

 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 

因为在Derived.method() type(self)Subclass而不是 Derived

在这个例子中, Subclass的MRO是[Subclass, Derived, Base] ,而super()需要知道从哪里开始search任何重写的方法。 通过使用type(self)你告诉它从Subclass开始,所以它会在下一个findDerived.method() ,这是我们开始的地方。

self.__class__可能不是一个子类,而是一个孙辈或更年轻的类,从而导致一个堆栈中断循环。