2014-04-22 62 views
40

假設我們想要的一些代碼塊被執行時都「一」和「b」等於說5,然後我們就可以像寫:Python的平等檢查差異

if a == 5 and b == 5: 
    # do something 

但前幾天,我只是不由自主地寫了一個類似的條件檢查:

if a == b and b == 5: 
    # do something 

這使我想到,是兩者之間有什麼區別? 此外,還有一個別的辦法,

if a == b == 5: 
    # do something 

有什麼不同,在評估或執行或時間的過程方面有什麼區別多久?還有哪一個更好,哪個更好用?

它與傳遞性的概念有關嗎?

+3

所有這三個將在相同數量的執行時間,並且在邏輯上是等同的。就執行時間而言,三種方法中的任何一種都需要'int'類型之間的兩次等式比較。就程序員而言,哪個更好,哪些更好,清晰可讀。 – CoryKramer

+1

'a < b > 5'和'a> b == 5'也是可能的(我注意到Jasper引用的文檔說「比較可以被任意鏈接」)。但我不會推薦他們。 –

+0

@TimS。 「b在a和5之間」實際上似乎相當有用,並且比'a < b and b > 5'更可讀,但那只是我。我同意'a> b == 5'雖然有點不穩定.. – Cruncher

回答

41

因爲它們是等價的基本上,你也可以考慮一下你的讀/想想代碼的方式:

if a == 5 and b == 5: 
    # do something 

可以爲「如果a等於5b等於5,然後做......「。你必須認爲/結論,然後a將等於b

這是對着下面的例子:

if a == b and b == 5: 
    # do something 

讀取爲「如果a等於bb等於5」,你必須斷定這隨後也a會等於5

這就是爲什麼我更喜歡最後一個例子:

if a == b == 5: 
    # do something 

如果你熟悉Python(感謝Itzkata)其作用是立即清除所有的三兩件事必須等於(以5)。然而,如果人們在Python(但在其他語言編程技能)經驗少看到這種情況,他們會評估這

if (a == b) == 5: 

這會比較整數5,這是不是第一次比較的布爾結果什麼Python做,可能會導致不同的結果(例如考慮與a=0, b=0a==b==0是真實的,而(a==b) == 0

manual說:

Python中有八個比較操作。它們都有 相同的優先級(比布爾操作的優先級高)。 比較可以任意鏈接;例如,X <ÿ< = z是 等價於x < y和y < = Z,不同之處在於y爲只計算一次 (但在這兩種情況下z爲不計算在所有當x < y被發現是 false)。

甚至可能有區別,例如,如果在您的示例中揮發b會產生副作用。

關於傳遞性,你是對的。

+0

@Jasper你能幫我在這裏!假設a = 5且b = 4,那麼根據第二種情況,a == b將是假的,並且下一個條件將不被檢查,因此對於這個(假)條件將只有少於1個測試,即只有1個比較。而在所有其他情況下總是有2個比較。所以在這種情況下應該有一個邊際的速度改善。如果我錯了,請糾正我。 – Vipul

+1

如果我正確理解手冊,'a == b == 5'等價於'a == b和b == 5',所以對於'a = 5','b = 4',第二個測試' b == 5'不會被執行。另見羅伯託的回答。 – Jasper

+0

你從哪裏得到「Python中有八個比較運算符。」從?我數6:'<','<=','==','!=','>','> ='...我錯過了哪兩個? – ArtOfWarfare

6

這取決於。你可以寫自己的自定義__eq__它允許您將自己比作整數,事情:「INT」

class NonNegativeInt(object): 
    def __init__(self, value): 
    if value < 0: 
     raise Exception("Hey, what the...") 
    self.value = value 

    def __eq__(self, that): 
    if isinstance(that, int): 
     return self.value == that 
    elif isinstance(that, NonNegativeInt): 
     return self.value == that.value 
    else: 
     raise ArgumentError("Not an acceptible argument", "__eq__", that) 

這將工作不同,這取決於「B」比較「A」和「B」至因此,a == b可能爲false,而a == 5 and b == 5可能爲True。

+9

對不起,有一個不專業的評論,但我認爲''嘿,什麼......鴨子「會更加pythonic IMO =)。不能幫助自己。 – luk32

15

就整數而言,在前兩次比較之間,就純粹的性能而言,沒有區別。

雖然第三個比較是不同的,因爲更多一點擺弄堆棧捲入。事實上,代碼

import dis 

def comparison_1(a, b): 
    if a == 5 and b == 5: 
     pass 

def comparison_2(a, b): 
    if a == b and b == 5: 
     pass 

def comparison_3(a, b): 
    if a == b == 5: 
     pass 

print("*** First comparison ***") 
dis.dis(comparison_1) 

print("\n*** Second comparison ***") 
dis.dis(comparison_2) 

print("\n*** Third comparison ***") 
dis.dis(comparison_3) 

回報

*** First comparison *** 
    4   0 LOAD_FAST    0 (a) 
       3 LOAD_CONST    1 (5) 
       6 COMPARE_OP    2 (==) 
       9 POP_JUMP_IF_FALSE  27 
      12 LOAD_FAST    1 (b) 
      15 LOAD_CONST    1 (5) 
      18 COMPARE_OP    2 (==) 
      21 POP_JUMP_IF_FALSE  27 

    5   24 JUMP_FORWARD    0 (to 27) 
     >> 27 LOAD_CONST    0 (None) 
      30 RETURN_VALUE   

*** Second comparison *** 
    8   0 LOAD_FAST    0 (a) 
       3 LOAD_FAST    1 (b) 
       6 COMPARE_OP    2 (==) 
       9 POP_JUMP_IF_FALSE  27 
      12 LOAD_FAST    1 (b) 
      15 LOAD_CONST    1 (5) 
      18 COMPARE_OP    2 (==) 
      21 POP_JUMP_IF_FALSE  27 

    9   24 JUMP_FORWARD    0 (to 27) 
     >> 27 LOAD_CONST    0 (None) 
      30 RETURN_VALUE   

*** Third comparison *** 
12   0 LOAD_FAST    0 (a) 
       3 LOAD_FAST    1 (b) 
       6 DUP_TOP    
       7 ROT_THREE   
       8 COMPARE_OP    2 (==) 
      11 JUMP_IF_FALSE_OR_POP 23 
      14 LOAD_CONST    1 (5) 
      17 COMPARE_OP    2 (==) 
      20 JUMP_FORWARD    2 (to 25) 
     >> 23 ROT_TWO    
      24 POP_TOP    
     >> 25 POP_JUMP_IF_FALSE  31 

13   28 JUMP_FORWARD    0 (to 31) 
     >> 31 LOAD_CONST    0 (None) 
      34 RETURN_VALUE   
+3

我很驚訝Python爲第三次比較生成這樣複雜的代碼... – nneonneo

+1

這是什麼版本的Python? – Izkata

19

如果你有多個變量來進行測試,使用all可能會稍微更可讀:

if all(i==5 for i in [a,b,c,d]): 
    # do something 
+0

超過2個變量的pythonic最多。 – Jasper