Python 的比較運算子(又稱為 Python 關係運算子)會查看兩個運算元的_值_,並在comparison條件成立或不成立時回傳布林值True或False。
下表列出最常見的 Python 比較運算子:
| 運算子 | 運算 | 說明 |
|---|---|---|
> |
「大於」 | 若a的值嚴格大於b,則a > b為True
|
< |
「小於」 | 若a的值嚴格小於b,則a < b為True
|
== |
「等於」 | 若a的值嚴格等於b,則a == b為True
|
>= |
「大於或等於」 | 若a的值大於b或等於b,則a >= b為True
|
<= |
「小於或等於」 | 若a的值小於b或等於b,則a <= b為True
|
!= |
「不等於」 | 若a == b為False,則a != b為True
|
is |
「同一性」 | 若且唯若a和b是相同的_物件_,則a is b為True
|
is not |
「否定的同一性」 | 若且唯若a和b不是相同的_物件_,則a is not b為True
|
in |
「包含測試」 | 若a是b的成員、子集或元素,則a in b為True
|
not in |
「否定的包含測試」 | 若a不是b的成員、子集或元素,則a not in b為True
|
它們的優先順序都相同(高於布林運算,但低於算術或位元運算)。
不同型別的物件(數值型別除外)預設永遠不會比較為相等。
除非class定義了特殊的豐富比較方法來自訂預設的object比較行為,否則同一個class的非相同實例也不會比較為相等。
如需(更多)細節,請參閱 Python 文件中的值比較。
數值型別(大致上)是這項型別配對規則的例外。
只要型別能為了比較而隱含轉換,integer可以被視為等於float(或是octal等於hexadecimal)。
至於其他數值型別(複數、十進位數、分數),比較運算子定義在「合理」的地方(隱含轉換不會改變結果的地方),但如果底層物件無法為了比較而精確轉換,就會擲回TypeError。
關於 Python 數值轉換所用規則的更多資訊,請參閱 Python 文件中的算術轉換。
>>> import fractions
# A string cannot be converted to an int.
>>> 17 == '17'
False
# An int can be converted to float for comparison.
>>> 17 == 17.0
True
# The fraction 6/3 can be converted to the int 2
# The int 2 can be converted to 0b10 in binary.
>>> 6/3 == 0b10
True
# An int can be converted to a complex
# number with a 0 imaginary part.
>>> 17 == complex(17)
True
# The fraction 2/5 can be converted to the float 0.4
>>> 0.4 == 2/5
True
>>> complex(2/5, 1/2) == complex(0.4, 0.5)
True
任何數字與NaN(非數字)型別進行的有序比較結果都是False。
Python 對NaN的定義有個令人困惑的副作用:NaN永遠不會比較為等於NaN。
如果你好奇 Python 為何這樣定義NaN,這篇圍繞國際標準制定、Stack Overflow 上關於 NaN 的文章值得一讀。
>>> x = float('NaN')
>>> 3 < x
False
>>> x < 3
False
# NaN never compares equal to NaN
>>> x == x
False
字串(str)會依字典序比較,比較時使用各自獨立的 Unicode 碼位(也就是把str中的每個碼位傳入內建函式ord()的結果,該函式會回傳一個int)。
如果兩個字串中的所有碼位都相符,且_順序相同_,就視為相等。
這項比較是以「成對」方式進行的:第一個對第一個、第二個對第二個,依此類推。
在 Python 3.x 中,str與bytes無法直接強制轉換或比較。
>>> 'Python' > 'Rust'
False
>>> 'Python' > 'JavaScript'
True
# Examples with Mandarin.
# hello < goodbye
>>> '你好' < '再见'
True
# ord() of first characters
>>> ord('你'), ord('再')
(20320, 20877)
# ord() of second characters
>>> ord('好'), ord('见')
(22909, 35265)
# And with Korean words.
# Pretty < beautiful.
>>> '예쁜' < '아름다운'
False
>>> ord('예'), ord('아')
(50696, 50500)
容器資料型態(lists、tuples、sets、dicts等)同樣依字典序比較:如果兩個容器有相同的資料且相同的資料型態(就lists和tuples而言,它們也必須有相同的順序),則兩者相等,否則不相等。
>>> [1, 2] == [1, 2]
True
# But if the data is not in the same order, they are not equal.
>>> [2, 1] == [1, 2]
False
# The same holds true for tuples
>>> (3,4,5) == (5,4,3)
False
# Length is also compared
>>> [1, 2] < [1, 2, 3]
True
# Comparing dicts
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 18}
False
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 19}
True
比較運算子可以_任意_串接。
請注意,運算式的求值是由left到right進行的。
例如,x < y <= z等價於x < y and y <= z,差別在於y只會被求值一次。
在這兩種情況下,當x < y被判定為False時,z完全不會被求值。
這通常稱為short-circuit evaluation:如果運算式的真值已經確定,求值就會停止。
Short circuiting獲得各種布林運算子、函式的支援,Python 中的比較鏈也支援它。
與許多其他程式語言(包括C、C++、C#和Java)不同,Python 中像a < b < c這樣的鏈式運算式具有傳統的數學詮釋與優先順序。
>>> x = 2
>>> y = 5
>>> z = 10
>>> x < y < z
True
>>> x < y > z
False
>>> x > y < z
False
運算子is和is not測試的是物件的同一性,而非物件的_值_。
物件建立之後,其同一性永遠不會改變,可以透過id()函式取得。
若且唯若id(<apple>) == id(<orange>),<apple> is <orange>的求值結果為True。
<apple> is not <orange>則會得到相反的結果。
由於None和NotImplemented具有單例狀態,比較項目時應一律使用is和is not。
關於這項慣例的更多細節,請參閱 Python 參考文件中的值比較與 PEP8。
# A list of favorite numbers.
>>> my_fav_numbers = [1, 2, 3]
>>> your_fav_numbers = my_fav_numbers
>>> my_fav_numbers is your_fav_numbers
True
# The returned id will differ by system and Python version.
>>> id(my_fav_numbers)
4517478208
# your_fav_numbers is only an alias pointing to the original my_fav_numbers object.
# Assigning a new name does not create a new object.
>>> id(your_fav_numbers)
4517478208
>>> my_fav_numbers is not your_fav_numbers
False
>>> my_fav_numbers is not None
True
>>> my_fav_numbers is NotImplemented
False
運算子in和not in測試的是_成員資格_。
若<fish>是<soup>的成員(若<fish>是<soup>的子集或包含於<soup>之中),則<fish> in <soup>的求值結果為True,否則為False。
<fish> not in <soup>會回傳其否定,也就是<fish> in <soup>的_相反_。
就字串和 bytes 型別而言,若且唯若<name>是<fullname>的子字串,<name> in <fullname>才會是True。
# A set of lucky numbers.
>>> lucky_numbers = {11, 22, 33}
>>> 22 in lucky_numbers
True
>>> 44 in lucky_numbers
False
# A dictionary of employee information.
>>> employee = {'name': 'John Doe', 'id': 67826, 'age': 33, 'title': 'ceo'}
# Checking for the membership of certain keys.
>>> 'age' in employee
True
>>> 33 in employee
False
>>> 'lastname' not in employee
True
# Checking for substring membership
>>> name = 'Super Batman'
>>> 'Bat' in name
True
>>> 'Batwoman' in name
False
物件的比較行為可以透過實作rich comparison methods來自訂。
如需更多資訊,請參閱 Python 教學:類別、Python 類別與魔術方法(Dan Bader) 以及特殊方法名稱。