我希望能夠遍歷給定類的所有基類(包括類本身)的直接和間接基類。如果您有一個元類來檢查所有基類的內部Options類,那麼這很有用。是否有一個標準函數來迭代基類?
要做到這一點,我寫了下面:
def bases(cls):
yield cls
for direct_base in cls.__bases__:
for base in bases(direct_base):
yield base
有沒有一個標準功能爲我做到這一點?
我希望能夠遍歷給定類的所有基類(包括類本身)的直接和間接基類。如果您有一個元類來檢查所有基類的內部Options類,那麼這很有用。是否有一個標準函數來迭代基類?
要做到這一點,我寫了下面:
def bases(cls):
yield cls
for direct_base in cls.__bases__:
for base in bases(direct_base):
yield base
有沒有一個標準功能爲我做到這一點?
有一種方法可以將它們全部返回,方法分辨率排序(MRO):inspect.getmro
。在這裏看到:
http://docs.python.org/library/inspect.html#inspect.getmro
它返回它們作爲一個元組,然後你就可以自己遍歷在一個循環:
import inspect
for base_class in inspect.getmro(foo):
# do something
這有隻得到每個基類,一旦附帶的好處,即使你有鑽石圖案的繼承。
我完全不知道這是否是你在找什麼,但看看someclass.__mro__
,MRO是方法解析順序
http://docs.python.org/library/stdtypes.html?highlight=mro#class.__mro__
琥珀已經爲正確答案真實世界,但我會展示一個正確的方法來做到這一點。如果兩個基類本身從同一個基類繼承,那麼您的解決方案將包含一些類兩次。
def bases(cls):
classes = [cls]
i = 0
while 1:
try:
cls = classes[i]
except IndexError:
return classes
i += 1
classes[i:i] = [base for base in cls.__bases__ if base not in classes]
唯一稍微棘手的部分是我們使用切片的地方。這是執行這種深度優先搜索而不使用遞歸所必需的。它所做的就是取當前正在檢查的類的基類,並在它後面立即插入它們,以便第一個基類成爲下一個檢查的類。標準庫中的inspect.getmro
的實現中有一個非常可讀的解決方案(具有它自己的醜陋)。
謝謝。我發佈後,我意識到,我可能會兩次打同一班,但在我的情況下,這並不重要。 – 2010-11-04 15:16:56
這有(不可爭辯的)不利用舊式課程的缺點。 'inspect.getmro'返回'cls .__ mro__'(如果它存在於新樣式類中),如果不存在則執行自定義搜索。 (有趣的事實:你可以通過創建一箇舊類風格的類層次結構來產生遞歸錯誤,類層次比最大遞歸深度更多,並調用'getmro') – aaronasterling 2010-11-04 07:56:25