2013-08-02 41 views
4

我正在使用一些現有的代碼重新定義類的平等(通過__cmp__方法)。它沒有按預期工作,並試圖解決它我遇到了一些我不明白的行爲。如果你在一個只調用內置函數cmp的類上定義了__cmp__,那麼我認爲它總是會達到最大遞歸深度。不過,如果你試圖將類的實例比較本身則返回0在python和遞歸中瞭解cmp

下面的代碼:

class A: 
    def __cmp__(self, other): 
     return cmp(self, other) 

a = A() 
b = A() 
cmp(a, a) # returns 0 
cmp(b, b) # returns 0 
cmp(a, b) # results in RuntimeError: maximum recursion depth exceeded 

的RuntimeError我理解,但我不明白爲什麼前兩個電話給cmp成功。

我已閱讀了python文檔的data model部分以及其他諸如python equality的細分項,但無法找到此遞歸的答案。

而且,我知道這是一個完全沒有意義的課程。我正在使用的代碼嘗試在某些情況下重新定義相等性,否則將落入一個基本情況。 basecase不能正常工作,所以我試圖修復它。我想打電話cmp可能會工作,並發現這個問題。我希望理解這將幫助我找到合適的解決方案。

+0

我試過相同的代碼,但沒有得到任何錯誤 –

+0

@AswinMurugesh - 你使用的是什麼版本的Python?我使用2.7.3 –

+0

我也使用2.7.3 –

回答

1

如果兩個名字引用相同的對象,他們是通過定義等於(編輯:至少就cmp而言,這裏的「平等」的真正含義「既不比大於也沒少」)。

+1

不一定。 'float('nan')'不等於它自己。 – user2357112

+0

@ user2357112:這裏有一個關於'cmp'與'NaN'行爲的線程:http://mail.python.org/pipermail/python-dev/2004-May/044885.html恐怕我不會沒有時間閱讀它的結論。 :-)我確實得到了Tim Peters的說法:「cmp(x,y)對於只有部分排序的對象沒有意義,所以我不在乎cmp()如何處理NaN。 「 – RichieHindle

+1

好吧,我根據這個答案做了一些更多的測試。看起來像'cmp(a,a)'甚至不調用'__cmp__'方法。它只是返回0的快捷方式。這意味着'cmp(x,x)'不總是與'x .__ cmp __(x)'相同。有點混亂但可以理解。 –

1

由於cmp語義要求被比較的對象具有一個順序關係(即完全以下之一在​​呼叫爲真:x < yx == y,或x > y),cmp可以假設一種說法是等於如果參數是相同的對象,則跳過對任何比較方法的調用。

(很多在Python中的東西假定任何對象xx == x。這有時會導致錯誤(尤其是與南浮點值),但大部分時間,這是一個非常有用的優化。在cmp的情況下,這是很好的,因爲cmp需要x == x爲前提,以cmp(x, x))。

+0

你可以(如果你瘋了)以'x == x'爲'False'的方式定義相等性,但'cmp(x,x)'仍然會返回0.但是你所說的是'cmp '假設你沒有那麼瘋狂。 –

+0

@ChrisPalmer:就像user2357112指出的那樣,'NaN'就是這種情況。但是'NaN' *當然是瘋了,所以沒關係。 :-) – RichieHindle

0

cmp(a,a)被調用內置cmp。沒有看源代碼,我猜0123:檢查是在沒有調用__cmp__類的情況下進行的。如果兩個對象不相同,則調用然後__cmp__