2010-11-04 117 views
5

我希望能夠遍歷給定類的所有基類(包括類本身)的直接和間接基類。如果您有一個元類來檢查所有基類的內部Options類,那麼這很有用。是否有一個標準函數來迭代基類?

要做到這一點,我寫了下面:

def bases(cls): 
    yield cls 
    for direct_base in cls.__bases__: 
     for base in bases(direct_base): 
      yield base 

有沒有一個標準功能爲我做到這一點?

回答

12

有一種方法可以將它們全部返回,方法分辨率排序(MRO):inspect.getmro。在這裏看到:

http://docs.python.org/library/inspect.html#inspect.getmro

它返回它們作爲一個元組,然後你就可以自己遍歷在一個循環:

import inspect 
for base_class in inspect.getmro(foo): 
    # do something 

這有隻得到每個基類,一旦附帶的好處,即使你有鑽石圖案的繼承。

0

我完全不知道這是否是你在找什麼,但看看someclass.__mro__,MRO是方法解析順序

http://docs.python.org/library/stdtypes.html?highlight=mro#class.__mro__

+1

這有(不可爭辯的)不利用舊式課程的缺點。 'inspect.getmro'返回'cls .__ mro__'(如果它存在於新樣式類中),如果不存在則執行自定義搜索。 (有趣的事實:你可以通過創建一箇舊類風格的類層次結構來產生遞歸錯誤,類層次比最大遞歸深度更多,並調用'getmro') – aaronasterling 2010-11-04 07:56:25

1

琥珀已經爲正確答案真實世界,但我會展示一個正確的方法來做到這一點。如果兩個基類本身從同一個基類繼承,那麼您的解決方案將包含一些類兩次。

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的實現中有一個非常可讀的解決方案(具有它自己的醜陋)。

+0

謝謝。我發佈後,我意識到,我可能會兩次打同一班,但在我的情況下,這並不重要。 – 2010-11-04 15:16:56

相關問題