比較、指定、邏輯運算
April 12, 2022對於大於、小於、等於這類的比較,Python 提供了 >、>=、<、<=、==、!= 等運算子。
比較運算
比較運算有個很 Python 的特色,就是可以串接在一起,例如 x < y <= z,其實相當於 x < y and y <= z,and 是布林運算子,表示「而且」。如果願意,也可以像 w == x == y == z 這樣一直串接下去。
請注意不要將 ==、!= 與 is 及 is not 搞混,==、!= 是比較物件實際的值、狀態等的相等性,而 is 及 is not 是比較兩個物件的參考是否相等。
想知道物件是否能進行 >、>=、<、<=、==、!= 等比較,以及它們比較之後的結果為何,應該看看它們的 __gt__、__ge__、__lt__、__le__、__eq__ 或 __comp__ 等方法如何實作。
對於數值型態,進行 >、>=、<、<=、==、!= 等比較沒有問題,就是比較數字,至於其他型態,可以先知道的是,字串與 list 也能進行 >、>=、<、<=、==、!=,字串會逐字元依字典順序來比較,因此 'AAC' < 'ABC' 會是 True,'ACC' < 'ABC' 會是 False。
你可以寫一個簡單的程式,透過命令列引數指定兩個字串,看看比較的結果:
import sys
str1 = sys.argv[1]
str2 = sys.argv[2]
print(f'"{str1}" > "{str2}" ? {str1 > str2}')
print(f'"{str1}" == "{str2}" ? {str1 == str2}')
print(f'"{str1}" < "{str2}" ? {str1 < str2}')
一個執行結果如下:
>python compare.py Justin Monica
"Justin" > "Monica" ? False
"Justin" == "Monica" ? False
"Justin" < "Monica" ? True
至於 list,是逐元素進行比較,因此 [1, 2, 3] == [1, 2, 3] 結果是 True,然而 [1, 2, 3] > [1, 3, 3] 結果會是 False。
指定運算
到目前為止只看過一個指定運算子,也就是 = 運算子,事實上指定運算子還有以下幾個:
| 指定運算子 | 範例 | 結果 |
|---|---|---|
| += | a += b | a = a + b |
| -= | a -= b | a = a - b |
| *= | a *= b | a = a * b |
| /= | a /= b | a = a / b |
| %= | a %= b | a = a % b |
| &= | a &= b | a = a & b |
| = | a |= b | a = a | b |
| ^= | a ^= b | a = a ^ b |
| <<= | a <<= b | a = a << b |
| >>= | a >>= b | a = a >> b |
指定運算子構成了陳述句(Statement)而不是運算式(Expression),也就是這些指定運算子不會有傳回值,因此無法作為函式呼叫時的引數,或任何需要運算式的場合,例如:
>>> print(a = 10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'a' is an invalid keyword argument for print()
>>>
從 Python 3.8 開始,新增了指定運算式(Assignment Expressions )特性,透過 := 運算子,可以完成指定,而且會將指定的值作為結果傳回,例如:
>>> print(a := 10)
10
>>>
因為 := 運算子橫著看,像個海象的臉,社群中亦稱其為海象運算子(Walrus Operator),然而對其有正反面不同的看法,有些開發者認為某些場合中它很有用,另一群開發者覺得這讓指定必須區分陳述句、運算式的不同,也可能被濫用而令程式碼變得複雜。
我的看法是,一切以可讀性為優先,如果有助於閱讀程式就使用。
邏輯運算
在邏輯上有所謂的「且」、「或」與「反相」,Python 也提供對應的邏輯運算子(Logical operator),分別為 and、 or 及 not。底下這個程式是個簡單的示範,可以判斷命令列引數指定的兩個字串大小寫關係:
import sys
str1 = sys.argv[1]
str2 = sys.argv[2]
print('兩個都大寫?', str1.isupper() and str2.isupper())
print('有一個大寫?', str1.isupper() or str2.isupper())
print('都不是大寫?', not (str1.isupper() or str2.isupper()))
一個執行結果如下:
>python uppers.py Justin MONICA
兩個都大寫? False
有一個大寫? True
都不是大寫? False
將 None、False、0、0.0、0j、''、()、[]、{} 等傳給 bool,都會傳回 False,這些型態的其他值傳入 bool,都會傳回 True。在 and、or、not 運算時,遇到非 bool 型態時,也是這麼判斷。例如,若 value 為 None、False、0、0.0、0j、''、()、[]、{} 等其中之一,那麼 not value 結果都會是 True。
and、or 有捷徑運算的特性。and 左運算元若判定為假,就可以確認邏輯不成立,因此不用繼續運算右運算元;or 是左運算元判斷為真,就可以確認邏輯成立,不用再運算右運算元。當判斷確認時停留在哪個運算元,就會傳回該運算元,例如:
>> [] and 'Justin'
[]
>>> [1, 2] and 'Justin'
'Justin'
>>> [] or 'Justin'
'Justin'
>>> [1, 2] or 'Justin'
[1, 2]
>>>


