我有一個三類繼承鏈:Baz繼承自繼承自Foo的Bar。我想在Foo類中定義一個方法,當它在子類中調用時,會返回其父類的輸出,並附加它自己的東西。這是所需的輸出:Python:超越最大遞歸深度,同時調用子類的超類方法
>>> foo = Foo()
>>> bar = Bar()
>>> baz = Baz()
>>> print foo.get_defining_fields()
['in Foo']
>>> print bar.get_defining_fields()
['in Foo', 'in Bar']
>>> print baz.get_defining_fields()
['in Foo', 'in Bar', 'in Baz']
的問題是,我誤解一些有關超類方法使用super()
由子類調用,或一些其他子類的細節。該位工作正常:
>>> print foo.get_defining_fields()
['in Foo']
但bar.get_defining_fields()
產生無限循環,運行本身,直到RuntimeError
改爲引發呼喚foo.get_defining_fields
和停止那裏,像我想它的。
這是代碼。
class Foo(object):
def _defining_fields(self):
return ['in Foo']
def get_defining_fields(self):
if self.__class__ == Foo:
# Top of the chain, don't call super()
return self._defining_fields()
return super(self.__class__, self).get_defining_fields() + self._defining_fields()
class Bar(Foo):
def _defining_fields(self):
return ['in Bar']
class Baz(Bar):
def _defining_fields(self):
return ['in Baz']
所以get_defining_fields
在超類中定義的,在它的super()
通話,試圖通過正確的子類名在每個子類中調用使用self.__class__
。在Bar中調用時,它會解析爲super(Bar, self).get_defining_fields()
,以便foo.get_defining_fields()
返回的列表將被預置爲由far.get_defining_fields()
返回的列表。
如果你正確理解Python的繼承機制和super()
的內部工作原理,這可能是一個簡單的錯誤,但是因爲我顯然不這樣做,所以如果有人能指出我正確的方式來做這件事,我會很感激。
編輯:按照丹尼爾·羅斯曼的答案,我試圖用這種形式代替super()
電話:return super(Foo, self).get_defining_fields() + self._defining_fields()
現在無限遞歸不再出現,但調用bar.get_defining_fields()
當我得到一個不同的錯誤:
AttributeError: 'super' object has no attribute 'get_defining_fields'
別的東西還是不對。
編輯:是的,終於想通了什麼,我在這裏失蹤。將丹尼爾的最新答案標記爲已接受的答案。
@Charles蒂:這是真實的Python 3,所有類新的類,但在Python 2中不鼓勵。 – jena
我刪除了我的評論,但之前我問過他爲什麼從對象派生。因此,耶納的答覆。 –