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

2024-04-29 15:00:31 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

很好,很管用。但是,我发现自己在进行更改时经常在类之间复制和粘贴,而且经常忘记将派生类参数修复为super()函数。

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

看起来很有效,但我不应该这样做有什么好理由吗?


Tags: 方法函数selfbase参数粘贴基类stackoverflow
2条回答

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

不,你不能。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()

在本例中,Subclass的MRO是[Subclass, Derived, Base],并且super()需要知道从何处开始搜索任何重写的方法。通过使用type(self)你告诉它从Subclass开始,这样它就会找到Derived.method()下一个,这就是我们开始的地方。

相关问题 更多 >