看到 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 裡卻過了這麼久才實作出來呢?我覺得原因很明顯:

  1. 只要稍微注意一下,別在 boolean expression 裡放入太複雜的變數,意外的狀況不太會發生。
  2. boolean expression 本來就該愈短愈好,不該把 callable 放進去。
  3. 如果可能,用 if ... else ... 會更清楚,避免 boolean expression 即可。

雖然 Python 2.5 正式支援了 conditional expression,但它還是一個太年輕的 release。大部分的人為了向下相容主流的 Python 2.4 甚至 2.3,多半還是會選用舊式的 boolean expression。它和 relative import 一樣,都是看得到吃不到的好東西。我們只能靜待主流演進了。

Posted by yungyuc at 21:32, 0 comment, 0 trackback.
Navigate
Add a trackback
Add a comment

Your name. (required)

Your personal website. (optional)

Your email address. Will not show in page. (suggested, but optional)

Text format is "Plain Text".

Enter "whmpB"
© hover year to navigate month: powered by django