![](/img/trans.png)
[英]Python Operators: Math Precedence Comparison operators vs equality operators
[英]Comparison operators vs “rich comparison” methods in Python
有人可以解釋我兩者之間的差異。 那些通常是等價的嗎? 也許我在這里完全錯了,但我認為每個比較運算符都必然與一個“豐富的比較”方法有關。 這來自文檔:
運算符符號和方法名稱之間的對應關系如下:
x<y
調用x.__lt__(y)
,x<=y
調用x.__le__(y)
,x==y
調用x.__eq__(y)
,x!=y
調用x.__ne__(y)
,x>y
調用x.__gt__(y)
,x>=y
調用x.__ge__(y)
。
這是一個展示我困惑的例子。
Python 3.x:
dict1 = {1:1}
dict2 = {2:2}
>>> dict1 < dict2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'dict' and 'dict'
>>> dict1.__lt__(dict2)
NotImplemented
Python 2.x:
dict1 = {1:1}
dict2 = {2:2}
>>> dict1 < dict2
True
>>> dict1.__lt__(dict2)
NotImplemented
從python 3的例子來看,似乎不支持調用dict1 < dict2
邏輯。 但是Python 2的例子呢? 為什么接受?
我知道,與Python 2不同,在Python 3中,並非所有對象都支持比較運算符。 令我驚訝的是,兩個版本在調用__lt__()
時返回NotImplemented
單例。
這依賴於__cmp__
magic方法,這是富比較運算符要替換的方法:
>>> dict1 = {1:1}
>>> dict2 = {2:2}
>>> dict1.__cmp__
<method-wrapper '__cmp__' of dict object at 0x10f075398>
>>> dict1.__cmp__(dict2)
-1
至於排序邏輯 ,這里是Python 2.7 文檔 :
當且僅當它們具有相等(鍵,值)對時,映射(dict的實例)才相等。 鍵和值的相等比較強制實現反身性。
平等以外的結果一致地得到解決,但沒有另外定義。
用腳注:
早期版本的Python使用了排序(鍵,值)列表的詞典比較,但對於比較相等的常見情況,這是非常昂貴的。 甚至早期版本的Python僅通過標識比較字典,但這引起了驚喜,因為人們希望能夠通過將字典與{}進行比較來測試字典的空白。
而且,在Python 3.0中,訂購已經簡化。 這來自文檔 :
當操作數沒有有意義的自然順序時
(<, <=, >=, >)
排序比較運算符(<, <=, >=, >)
引發TypeError異常。
builtin.sorted()
和list.sort()
不再接受提供比較函數的cmp參數。 請改用key參數。應將
cmp()
函數視為已消失,並且不再支持__cmp__()
特殊方法。 使用__lt__()
進行排序,__eq__()
__hash__()
使用__hash__()
,並根據需要進行其他豐富的比較。 (如果你真的需要cmp()
功能,你可以使用表達式(a > b) - (a <> b)
作為cmp(a, b)
的等價物。)
所以,明確地說,在Python 2中,由於沒有實現豐富的比較運算符, dict
對象將從數據模型文檔中回退到__cmp__
:
object.__cmp__(self, other)
如果沒有定義豐富的比較(見上文),則通過比較操作調用。 如果self <other則返回負整數,如果self == other則返回0,如果self> other則返回正整數。
操作符<
對__lt__
注意事項:
import types
class A:
def __lt__(self, other): return True
def new_lt(self, other): return False
a = A()
print(a < a, a.__lt__(a)) # True True
a.__lt__ = types.MethodType(new_lt, a)
print(a < a, a.__lt__(a)) # True False
A.__lt__ = types.MethodType(new_lt, A)
print(a < a, a.__lt__(a)) # False False
<
在類上定義的調用__lt__
; __lt__
調用對象上定義的__lt__
。
它通常是相同的:)它使用起來非常好吃: A.__lt__ = new_lt
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.