如果你知道你總是應對新樣式類:
def numberofancestors(klass):
return len(klass.mro())
,或者,如果你擔心有可能是舊的樣式類的組合:
import inspect
def numberofancestors(klass):
return len(inspect.getmro(klass))
,然後在這兩種情況下,
sorted(HANDLERS, key=numberofancestors, reversed=True)
會給你你需要什麼(你不需要.keys()
部分)。
@伊格納西奧的拓撲排序的建議在理論上是正確的,但因爲給定一個類,你可以很容易和快速地得到它的前體的數量(AKA「祖先」... ...在一個奇怪的意義上,是你的祖先之一;-),通過這些函數,我的方法更加實用:它依賴於一個明顯的事實,即任何派生類至少比其任何基類都多一個「祖先」,因此,與此key=
,它總是會在其任何基地之前排序。
無關的類可能以任意順序結束(就像它們可能在拓撲排序中一樣),但是你已經明確表達了你並不在意這一點。
編輯:在OP,在下面的評論話題有關的多重繼承的情況下提供最佳支持沉思,想出了比「預排序」嵌入問題的最初一個完全不同的想法,但他的建議關於如何實現大幅度的想法是不是最佳:
的想法是好的(如多重繼承的支持是任何利息),但最好的實現其很可能是(Python的2.6或更高版本):
next(Handlers[c] for c in type(obj).mro() if c in Handlers)
通常情況下,adict.get(k) and check for not None
比if k in adict: adict[k]
快,但這不是一個特別正常的情況,因爲使用get
需要在其上建立一個「假」單項清單和「循環」來模擬分配。
更一般地,通過建立一個理解整個名單只是爲了利用其[0]
個項是多餘的工作 - 叫上genexp更像一個first
,如next
內置函數,「給我的第一項genexp「,除此之外沒有額外的工作。如果listcomp/genexp爲空,它將引發StopIteration而不是IndexError,但這通常不是問題;如果genexp爲空,您也可以使用next
的第二個參數作爲「默認值」。
在2.5和更早的版本中,您必須改用(thegenexp).next()
(而且沒有辦法給它一個默認參數),但是在語法上稍微有些閃亮,它或多或少等價於2.6更好的構造語義和速度。
我確信很高興繼續討論評論,因爲我認爲這個結論是有價值的並且可能有用(儘管可能不在OP的應用程序的確切環境中,其中多重繼承實際上可能不是問題) 。
非常聰明!這對於多繼承的情況並不適用,但我不打算處理這種用例。 – 2010-05-28 18:09:54
@Richard,你能告訴我一個多重繼承失敗的案例嗎?我想我已經證明沒有失敗的情況(多重或不是,派生類將永遠*至少有一個祖先 - 本身!),我想知道我的邏輯在哪裏使我失敗(或「我失敗了我的邏輯「;-) - 但我的腦袋因爲我無法想象_任何失敗的案例而受挫(當然,因爲繼承圖總是DAG)......它似乎抵消了大部分圖論的基本基礎。所以在此先感謝提供反例! – 2010-05-28 21:01:34
我沒有想太深,但是我想到的是這樣的: << class A; [A] ncestors = 1 // B類(A); a = 2 // class One; a = 1 // class Two(One); a = 2 // class Alice(B,One); a = 3 // class Bob(A,Two); a和3 // 寄存器(A,HandleA)// 寄存器(One,HandleOne)>> A和One具有相同的排序順序,因此它們的位置相對於彼此是未定義的。當我們去匹配Alice()或Bob()的實例時,我們將隨機獲得HandleA或HandleOne(因爲它們都是A和One的子類型)。無可否認,我很難想到這種情況何時會發生。 – 2010-05-29 02:32:54