不可思議,Python 的鏈?zhǔn)讲僮骶谷豢梢赃@樣
學(xué)習(xí) Python 的過程中,有沒有讓你出乎意料的情景,在細(xì)品之后,又覺得情理之中呢?(有的話文末留言哈)我就遇到過,初見時不可思議,仔細(xì)學(xué)習(xí)之后,又覺得豁然開朗,Python 的鏈?zhǔn)讲僮骶褪沁@樣的場景。
不可思議
比如說,你看到 True is False 的結(jié)果是 False, False is False 的結(jié)果是 True ,不會覺得有什么問題:
>>>?True?is?False
False
>>>?False?is?False
True
然后,當(dāng)你你看到 True is False is False 的結(jié)果是 False,可能就覺得不可思議。
>>>?True?is?False?is?False
False
>>>
因為無論是從前計算,還是從后計算,結(jié)果都應(yīng)該是 True ?。?/p>
>>>?(True?is?False)?is?False
True
>>>?True?is?(False?is?False)
True
>>>
豁然開朗
當(dāng)認(rèn)知和實際情況不一致的時候,恰恰是我們需要學(xué)修正自己的時候。這種操作屬于鏈?zhǔn)讲僮鳎琍ython 的官方文檔有解釋:https://docs.python.org/3/reference/expressions.html#comparisons

翻譯一下,大致意思就是 Python 中的比較運(yùn)算與 C 語言不同,這些比較操作具有相同的優(yōu)先級,該優(yōu)先級低于任何算術(shù),移位或按位運(yùn)算。
這些比較操作包括 in, not in, is, is not, <, <=, >, >=, !=, == 操作符,會產(chǎn)生 True 或 False 的結(jié)果,這些比較操作符號可以任意的鏈?zhǔn)奖容^,比如:x < y <= z,x < y 與 y <= z 具有相同的優(yōu)先級,不存在先計算 x < y ,得到結(jié)果后再與<=z 進(jìn)行比較的情況,因此x < y <= z 與 x < y and y <= z是等價的。
x < y and y <= z 中,如果 x < y 的結(jié)果是 False,那么 y <= z 根本不會被計算。
也就是說a op1 b op2 c ... y opN z 等價于 a op1 b and b op2 c and ... y opN z,每一個表達(dá)式最多被執(zhí)行一次。
注意,a op1 b op2 c 并不代表 a 和 c 有必然的關(guān)系,比如這樣寫x < y > z 也是合法的,雖然并不好看。
那么開始的問題就變得簡單了:
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?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)該避免這樣寫:
if?x??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??1:
????print("WHY??")
if?0??1?>>?y?<1??1:
????print("please?remove?this?from?the?language")
用法沒問題,但可能讓人產(chǎn)生疑問的,類似文章開頭的例子,也盡量避免:
if?0?1:
????print("x,y?in?(0,1)?with?x)
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]")
最后的話
編程細(xì)節(jié)藏著真知,搞懂了就豁然開朗,希望這些知識對你有用。如果您喜歡這篇文章,請點(diǎn)贊、轉(zhuǎn)發(fā)、關(guān)注,謝謝支持。
