比較、指定、邏輯運算
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]
>>>