今天在看別人代碼時看到這樣一種寫法, 感覺是個挺容易踩到的坑, 搞清楚後寫出來備忘.
Python中進行邏輯運算的時候, 默認采用的是一種叫做短路邏輯的運算規則. 名字是很形象的, 下面直接看代碼
print True and 1
# 1
print True or 1
# True
print False and 1
# False
print False or 1
# 1
可以看到, 雖然1會被當做布爾值計算, 但整個表達式的計算結果卻不一定是布爾值, 而是根據表達式的不同而不同. 上面幾個表達式不同的結果, 就是短路邏輯. 用大白話講, 就是一旦Python能判斷整個表達式是True還是False, 就不會進行後續的計算了, 就是邏輯被短路了, 後續的表達式被忽略了.
比如True or 1
的結果為True
就是因為不管or
後面是任何值, 整個式子的結果都必定是True, 所以Python看到True
, 看到or
, 後面的1就不看了, 1被短路了, 返回了True
; 同樣的False and 1
也是一樣, 看到False
然後是and
不管後面是什麼, 整個式子的結果必定是False
, 所以1被短路了, 返回False
.
相應的, 為什麼False or 1
會返回1, 就是因為False
和or
判斷不了式子的結果, 整個式子是True還是False, 是由or
後面的值來決定的, 所以Python要把整個式子看完, 所以返回1.
明白了什麼是短路邏輯之後, 我們看一看三目運算符
三目運算符, 又叫三元運算符. 熟悉Java的同學可能會知道, 它的形式是這樣的b?x:y
, 對於這個表達式來說, 如果條件b
為True
, 那表達式的結果就是x
, 如果b
為False
, 那表達式的結果就是y
. 這是一種很方便的寫法, 比if語句簡潔很多.
但Python中早期沒有類似寫法的三目運算符, 所以就出現了一種利用短路邏輯, 用and
和or
來模擬三目運算符的寫法, 下面我們看代碼
A = X and 'table' or False
這句代碼就是在利用短路邏輯模擬三目運算符, 當X
為True
的時候, A
會被賦值為'table'
, 當X
為Flase
的時候, A
會被賦值為False
;
乍一看好像很不錯, 但這種寫法卻有個坑, 我們看這句代碼
True and 0 or 1
如果我們把剛才的寫法當三目運算符來使用, 那麼條件語句是True
, 表達式應該返回0
才是我們期望的結果, 但實際上這個表達式會返回1
; 因為True and 0
的值為True
, 整個表達式的值是由or
之後的值來決定的, 所以Python會對後面的值做判斷, 導致返回了1
, 這就是為什麼and...or
這個寫法有坑的原因
如果想在Python中使用三目運算符, 可以使用if...else
寫法, 具體看代碼
# <為真時的結果> if <判定條件> else <為假時的結果>
0 if True else 1
用if...else
的寫法, 結果就會跟我們期望的相同, 當條件為True
時, 返回前面的值, 條件為False
時, 返回後面的值. 不會有坑, 只是寫的時候要注意, 條件和返回值的順序跟Java中的三目運算符不同, 不要搞錯即可