看到 Thinker 的「奇計淫巧」,便想對 Python 的 boolean expression 與 conditional expression 作點探討與整理。
在 2.5 版以前,Python 沒有真正的 conditional expression。但為了讓程式看起來緊緻美觀,許多人拿 boolean expression 勉強對付著用用。我們一定常常可以看到別人寫出這樣的 Python code:
value = True and "Option1" or "Option2"
這便是一道 boolean expression,它等效於:
if True: value = "Option1" else: value = "Option2"
如此一來,一組 if ... else ... 在一道表示式裡就解決了,十分方便。
不過,這種 boolean expression 其實不能取代所有簡單的 if ... else ...。讓我們來看一段碼:
def func1(): return False def func2(): return True value = True and func1() or func2()
最後的 value 應該是多少?答案是 True。為什麼不是 func1() 傳回的 False?因為 True and func1() 的值是 False,使得後面跟的 or 表示式變成:
False or func2()
這個運算的結果會是 func2() 的傳回值。因此答案不是我們預期由 func1() 傳回的 False,而是 func2() 傳回的 True!
也就是說,當評估 value = CONDITION and EXP1 or EXP2 表示式時,並不會完全轉換為預期中的
if CONDITION: value = EXP1 else: value = EXP2
而會依照 EXP1 表示式的傳回值而有所不同。只要 EXP1 的傳回值會被評估為邏輯假值,以上的轉換便不見得成立。
很麻煩,這真是太麻煩了。雖然 CONDITION and EXP1 or EXP2 看起來是個聰明的技巧,漂亮地應用了 Python 的 boolean expression 特性,不過卻可能會造成模糊不清的臭蟲。
在 Python 2.5 中引入了 PEP 308 所描述的 conditional expression,來解決這個問題。condition expression 的格式是:
value = EXP1 if CONDITION else EXP2
這個表示式便完全等效於:
if CONDITION: value = EXP1 else: value = EXP2
把 boolean expression 會隨著 EXP1 傳回值而改變行為的問題給解決了。
為什麼 C/C++ 中行之有年的 conditional expression 在 Python 裡卻過了這麼久才實作出來呢?我覺得原因很明顯:
- 只要稍微注意一下,別在 boolean expression 裡放入太複雜的變數,意外的狀況不太會發生。
- boolean expression 本來就該愈短愈好,不該把 callable 放進去。
- 如果可能,用 if ... else ... 會更清楚,避免 boolean expression 即可。
雖然 Python 2.5 正式支援了 conditional expression,但它還是一個太年輕的 release。大部分的人為了向下相容主流的 Python 2.4 甚至 2.3,多半還是會選用舊式的 boolean expression。它和 relative import 一樣,都是看得到吃不到的好東西。我們只能靜待主流演進了。
- Previous: FUSE/SSHFS workaround @2007/01/11
- Next: 有時候換個名詞,感覺起來就會不大一樣 @2007/01/15
Please send trackback to: http://blog.seety.org/everydaywork/2007/1/12/634/trackback/.