不可思議,Python 的鏈?zhǔn)讲僮骶谷豢梢赃@樣
學(xué)習(xí) Python 的過(guò)程中,有沒(méi)有讓你出乎意料的情景,在細(xì)品之后,又覺(jué)得情理之中呢?(有的話(huà)文末留言哈)我就遇到過(guò),初見(jiàn)時(shí)不可思議,仔細(xì)學(xué)習(xí)之后,又覺(jué)得豁然開(kāi)朗,Python 的鏈?zhǔn)讲僮骶褪沁@樣的場(chǎng)景。
不可思議
比如說(shuō),你看到 True is False 的結(jié)果是 False, False is False 的結(jié)果是 True ,不會(huì)覺(jué)得有什么問(wèn)題:
- >>> True is False
- False
- >>> False is False
- True
然后,當(dāng)你你看到 True is False is False 的結(jié)果是 False,可能就覺(jué)得不可思議。
- >>> True is False is False
- False
- >>>
因?yàn)闊o(wú)論是從前計(jì)算,還是從后計(jì)算,結(jié)果都應(yīng)該是 True 啊:
- >>> (True is False) is False
- True
- >>> True is (False is False)
- True
- >>>
豁然開(kāi)朗
當(dāng)認(rèn)知和實(shí)際情況不一致的時(shí)候,恰恰是我們需要學(xué)修正自己的時(shí)候。這種操作屬于鏈?zhǔn)讲僮?,Python 的官方文檔有解釋?zhuān)篽ttps://docs.python.org/3/reference/expressions.html#comparisons
翻譯一下,大致意思就是 Python 中的比較運(yùn)算與 C 語(yǔ)言不同,這些比較操作具有相同的優(yōu)先級(jí),該優(yōu)先級(jí)低于任何算術(shù),移位或按位運(yùn)算。
這些比較操作包括 in, not in, is, is not, <, <=, >, >=, !=, == 操作符,會(huì)產(chǎn)生 True 或 False 的結(jié)果,這些比較操作符號(hào)可以任意的鏈?zhǔn)奖容^,比如:x < y <= z,x < y 與 y <= z 具有相同的優(yōu)先級(jí),不存在先計(jì)算 x < y ,得到結(jié)果后再與<=z 進(jìn)行比較的情況,因此x < y <= z 與 x < y and y <= z是等價(jià)的。
x < y and y <= z 中,如果 x < y 的結(jié)果是 False,那么 y <= z 根本不會(huì)被計(jì)算。
也就是說(shuō)a op1 b op2 c ... y opN z 等價(jià)于 a op1 b and b op2 c and ... y opN z,每一個(gè)表達(dá)式最多被執(zhí)行一次。
注意,a op1 b op2 c 并不代表 a 和 c 有必然的關(guān)系,比如這樣寫(xiě)x < y > z 也是合法的,雖然并不好看。
那么開(kāi)始的問(wèn)題就變得簡(jiǎn)單了:
- True is False is False
相當(dāng)于
- (True is False) and (False is False)
結(jié)果自然就是 False。
相信,現(xiàn)在你已經(jīng)明白了下面的現(xiàn)象:
- >>> 1 in [0,1] == True
- False
- >>> not True in [True,False]
- False
然后,我再分享一下鏈?zhǔn)讲賾?yīng)用的好例子和壞例子。
好例子,一目了然:
- if 0 < x < 1:
- print("x in range (0,1)")
- if 0 <= x < 1:
- print("x in range [0,1)")
- if x <= y <= z:
- print("y in range [x,z]")
- if x >= y >= 1:
- print("y in range [1,x]")
- if x == y == z:
- print("x,y,z all equal")
壞例子,不知所云。我們應(yīng)該避免這樣寫(xiě):
- if x < y > z:
- print("y > max(x,z)")
- if x != y != z:
- print("kinda looks like x,y,z all distinct, but may have x==z")
- if 0 > x < y != z > 1:
- print("WHY??")
- if 0 < x > 1 >> y << 1 < z > 1:
- print("please remove this from the language")
用法沒(méi)問(wèn)題,但可能讓人產(chǎn)生疑問(wèn)的,類(lèi)似文章開(kāi)頭的例子,也盡量避免:
- if 0 < x < y == z < 1:
- print("x,y in (0,1) with x<y and z==y")
- if x <= y <= z != 1:
- print("y in range(x,z) with z != 1")
- if x == y == z != 1:
- print("x,y,z all equal something that isn't 1")
- if x is y is z:
- print("x,y,z all identical")
- if x is y is z in [1, 2, 3]:
- print("x,y,z all identical and in [1,2,3]")