欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python中 ? : 三元表達(dá)式的使用介紹

 更新時間:2013年10月09日 22:39:06   作者:  
剛剛學(xué)python的時候,時常糾結(jié)于python中沒有C語言中 ? : 的實現(xiàn),今天終于發(fā)現(xiàn)了兩種python的實現(xiàn)方式

(1) variable = a if exper else b
(2)variable = (exper and [b] or [c])[0]
(2) variable = exper and b or c

上面三種用法都可以達(dá)到目的,類似C語言中 variable = exper ? b : c;即:如果exper表達(dá)式的值為true則variable = b,否則,variable = c

例如:

復(fù)制代碼 代碼如下:

a,b=1,2
max = (a if a > b else b)
max = (a > b and [a] or [b])[0] #list
max = (a > b and a or b)


現(xiàn)在大部分高級語言都支持“?”這個三元運算符(ternary operator),它對應(yīng)的表達(dá)式如下:condition ? value if true : value if false。很奇怪的是,這么常用的運算符python居然不支持!誠然,我們可以通過if-else語句表達(dá),但是本來一行代碼可以完成的非要多行,明顯不夠簡潔。沒關(guān)系,在python里其實還是有對應(yīng)的表達(dá)方式的。

舉個例子:char *ret = (x!=0) ? "True" : "False"這行代碼對應(yīng)的python形式就是ret = (x and "True") or "False"(很簡單吧,事實上括號可以去掉)。運行時,python虛擬機會對賦值符右邊的布爾表達(dá)式(注意這里并非三元表達(dá)式)求值,返回值是最后一個被分析到的值。為什么是“最后一個被分析到的”而不是表達(dá)式中“最后一個”呢?因為布爾表達(dá)式有一個短路效應(yīng),比如a or b,如果a為真那么就不會分析b了。嗯,估計現(xiàn)在大家差不多明白了這行python代碼的原理了。如果x為真,由于字符串“True”也為真,于是返回"True",反之,x為假,那么就沒必要看字符串"True"了(短路效應(yīng)),直接返回"False"。

不難看出,三元運算在python中事實上可以通過借用布爾求值表達(dá)。然后,有時會有點小問題。舉個例子,char *ret = x ? "" or "VAL"。根據(jù)前面的例子,我們很自然想到在python里應(yīng)該這樣寫,ret = x and "" or "VAL"。錯了!不管x的布爾求值是真還是假,ret得到的總是"VAL"。奇怪么?不奇怪,因為在python中對空字符串的布爾求值為false,這樣x and ""永遠(yuǎn)都是false,所以ret得到的自然總是"VAL"了。解決這個問題有兩種辦法,第一種,也是我喜歡的一種,就是寫成ret = not x and "VAL" or ""。第二種,麻煩一點ret=x and [""] or ["VAL"],然后每次取ret[0]作為返回值,這是因為[""]在布爾求值時值為true。

討論一:第一種方法代碼明顯要簡潔,效率也高,那么還有必要使用第二種么?當(dāng)然,第一種辦法有局限性,只有當(dāng)我們非常明確其中一個值布爾求值時不可能為false時才能使用。在我們的示例中,由于"VAL"肯定返回true所以可以使用。如果是兩個變量呢,像這樣ret=x and val1 or val2,你就只能老老實實寫成ret=x and [val1] or [val2],然后取ret[0]作為結(jié)果了。因為這行語句所表達(dá)的不是“當(dāng)x為真返回val1,否則返回val2”,而是“當(dāng)x為真并且val1為真返回val2,否則返回val2”。

討論二:大家都知道python里有l(wèi)ist和tuple,前面這行代碼ret=x and [""] or ["VAL"]我們就是通過list解決,有的人可能偏愛tuple,于是就會這樣寫ret=x and ("") or ("VAL")。錯了!這里ret[0]永遠(yuǎn)都是空字符串(在2.5上測試)。這是我比較faint的一點,為啥[""]為真而("")為假呢?

最后,附上python對典型數(shù)值的布爾求值結(jié)果,這對我們書寫三元運算的等價語句很有用。

輸入 布爾求值
1,-1,[“”] True
0, “”, None, [], (), {}, (“”) False

python 三元表達(dá)式

之前學(xué)習(xí)的Python提到了對于類似C語言的三元條件表達(dá)式condition ? true_part : false_part,雖然Python沒有三目運算符(?:),但也有類似的替代方案,那就是true_part if condition else false_part。

復(fù)制代碼 代碼如下:

>>> 1 if True else 0
1
>>> 1 if False else 0
0
>>> "Fire" if True else "Water"
'Fire'
>>> "Fire" if False else "Water"
'Water'

在編程中我也一直這么用了,直到有一天發(fā)現(xiàn)了一個有趣的技巧,那就是and-or技巧,利用條件判斷的優(yōu)先特性來實現(xiàn)三元條件判斷,比如P∧Q,在Python中如果P為假,那么Python將不會繼續(xù)執(zhí)行Q,而直接判定整個表達(dá)式為假(P值),當(dāng)然如果P為真,那就還要繼續(xù)執(zhí)行Q來決定整個表達(dá)式值;同樣的P∨Q,如果P為真,那么就不會繼續(xù)執(zhí)行Q了…

其實很多編程語言在邏輯判斷中都應(yīng)用了這套機制,目前我接觸下來的貌似VB/VBScript可能不是這么做的。有了這套機制除了在if判斷中提高效率外,我們還可以額外發(fā)掘一些有趣的功能,比如下面的PHP代碼:

復(fù)制代碼 代碼如下:

$conn = @mysql_connect(...) or die("Failed")

如果mysql_connect成功的話將會返回resource資源句柄,如果失敗的話將會返回False,等等,后面還有個or,也就是失敗的話還將會繼續(xù)執(zhí)行or后面的die語句,于是輸出了錯誤信息并終止后續(xù)代碼的執(zhí)行。

再如下面的JavaScript代碼:

復(fù)制代碼 代碼如下:

function getEvent(e) {
    e = e || window.event;
    return e;
}

這段代碼獲取的是event,假如沒有給getEvent傳入值(即e為undefined),或者e為NULL(兩者在JavaScript條件中均代表False),e = e || window.event表達(dá)式將會把window.event賦值給e,否則e為Object對象,原表達(dá)式會蛻化為e = e賦值,也就是沒有改變什么。

好了,扯了這么多,稍稍有些偏題了,下面繼續(xù)聊Python的and-or技巧,可以這么說,這個技巧也是利用了邏輯判斷的特殊性,貌似在真正的三元表達(dá)式if else沒有出來的時候其就一直在扮演三元表達(dá)式的角色,其原型是condition and true_part or false_part,下面舉幾個例子:

復(fù)制代碼 代碼如下:

>>> True and 1 or 0
1
>>> False and 1 or 0
0
>>> True and "Fire" or "Water"
'Fire'
>>> False and "Fire" or "Water"
'Water'

但是值得注意的是雖然表面看上去能夠正常工作,其實還潛藏有不可知的風(fēng)險,若我們的true_part本身就是個被Python認(rèn)定為False的值,這個技巧就不可用了,我們知道空字符串就是這種情況。

復(fù)制代碼 代碼如下:

>>> True and "" or "Water"
'Water'

上面的表達(dá)式其實我們期望返回空字串的,如何解決呢,我在Dive Into Python中找到了解決方案:那就是利用列表特性,因為包含空字符串的列表其表達(dá)式值仍然為True,所以我們可以用列表先包裝一下,然后等表達(dá)式判斷完畢后在解包:

復(fù)制代碼 代碼如下:

>>> a = ""
>>> b = "Water"
>>> (True and [a] or [b])[0]
''

當(dāng)然為了避免出錯,我們可以將其包裝為函數(shù):

復(fù)制代碼 代碼如下:

def iif(condition, true_part, false_part):
    return (condition and [true_part] or [false_part])[0]

現(xiàn)在Python已經(jīng)在語言特性中加入三元條件表達(dá)式的支持了,那就是文章一開始介紹的if else寫法,所以為了妥善起見,對于三元判斷還是用新的if else特性吧,其實Python官方對于加入三元表達(dá)式語法也是討論了很久的,可以參考《PEP 308 — Conditional Expressions》。

相關(guān)文章

最新評論