比較

比較 在 Python

7 個練習

關於 比較

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) 以及特殊方法名稱。

透過 GitHub 編輯 連結會在新視窗或分頁中開啟

學習 比較

練習已鎖定

再解鎖 4 個練習,就能練習 比較