2010-05-14 20 views
5

所以我有一個襯墊:Python的行爲豐富的比較(或者,當十進制(「100.0」)<0.01)

import decimal; h = decimal.Decimal('100.0'); (h > .01, h < .01, h.__gt__(.01), h.__lt__(.01)) 

它所做的就是讓一個小數對象持有100.0,並進行比較到01(浮球)以各種方式。

我的結果是:

>>> import decimal; h = decimal.Decimal('100.0'); (h > .01, h < .01, h.__gt__(.01), h.__lt__(.01)) 
(False, True, NotImplemented, NotImplemented) 

從文檔:「豐富的比較方法可以返回,如果它不實施一對給定參數的操作NotImplemented單身。」

所以這裏真的有三個問題。

  1. 當一個豐富的比較方法返回NotImplemented,會發生什麼?爲什麼它不會引發異常?

  2. 當它得到NotImplemented時,它爲什麼會在第一種情況下返回False,在第二種情況下爲True?布爾(NotImplemented)應該是一個常量。

  3. 它是否會退回到id()檢查?似乎沒有(或肯定的,但向後):

(忽略此行,格式化被搞砸了,這修復它)

from decimal import Decimal 
h = Decimal('100.0') 
f = .01 
print h < f, id(h) < id(f) 
print h > f, id(h) > id(f) 

我的結果上測試:

Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] on win32 
Python 2.6.5 (r265:79096, Mar 19 2010, 21:48:26) [MSC v.1500 32 bit (Intel)] on win32 

編輯:關於訂購的文檔:http://docs.python.org/library/stdtypes.html#comparisons

回答

6

當豐富的比較方法返回 NotImplemented,會發生什麼?爲什麼 不會引發異常?

將其委託給逆方法(例如,__lt__當操作者>)RHS在比較(在float) - 在這種情況下也返回NotImplemented - 終於回落到Python的2的傻老異構比較規則。

當它被NotImplemented,爲什麼 它返回在第一種情況虛假,並 真在第二?bool(NotImplemented)應該是一個 常量。

沒有bool參與 - 因爲兩側對比返回NotImplemented(因故意設計決定不支持小數和浮點之間的任何操作),傻舊規則被用作回退(和在最近足夠的版本將比較類型,而不是實例 - 因此,id與它無關)。在Python 3中,這種不受支持的異構比較將會失敗,並引發一個明顯的異常,但在Python 2中,爲了向後兼容,它不可能發生 - 它必須繼續以在Python 2的整個生命週期內表現不佳的方式行事。

向後引入不兼容性解決現在被認爲是設計錯誤,像這部分約HET比較,是核心原因引進的Python 3.只要你堅持到Python 2(例如,因爲它有更多的第三方擴展等),你需要忍受這些僅在Python 3中修復的缺陷。

+0

啊,我不知道類型對象上的交叉類型排序。感謝您的明確解釋。 – 2010-05-14 14:50:15

+0

那麼,在經過大量的手動和鬍鬚拉動之後,Python 2.7中的規則已經放鬆了一點:現在小數和浮點實例相互比較明智。主要的技術問題是保留這樣的規則:比較相等的數字也應該相等。 (不要試圖比較小數和小數實例,但!) – 2010-05-25 08:48:14

0

我有Python 2.6.4和您的示例工作正常即我發現

(True, False, NotImplemented, NotImplemented) 

這是預期的。我不知道你爲什麼獲得不同的結果。

關於idID無關與比較,所以在任何情況下,你應該通過id(a) < id(b)比較ab,這沒有任何意義。 id有點像內存中的地址,所以比較它們根本沒有意義。

+0

如果對象沒有定義自己的比較,則將id()用作排序對象的最後手段。我不記得它的使用時間,但它確實是。你是對的,因爲它沒有意義,除非你試圖保證「對象的排序是一致的但是任意的(這樣排序異構數組會產生一致的結果)」,正如文檔指出的那樣,python確實。 – 2010-05-14 14:47:18

+0

它只是適合你的工作方式:嘗試999.01而不是0.1,你會看到完全相同的結果,向你展示它**不會**「正常工作」(這是一個停止的時鐘:一天兩次;-)。 _types_最終得到比較(並且這些類型的比較在不同的Python安裝中不需要以相同的方式工作),而不是人們通常期望的_values_。 – 2010-05-14 14:47:45

+0

@CB,'id'被用作_non-ordering_比較(等式和不等式)和散列的最後一個手段,它非常有意義;它從來沒有用於比較,比如'<'。相反,異構排序比較最終會比較_types_而不是值。 – 2010-05-14 14:49:36