2015-04-16 106 views
24

我發現別人的代碼這個奇怪的if語句來:奇怪的if語句

if variable & 1 == 0: 

我不明白。它應該有兩個==,對吧?

有人可以解釋一下嗎?

+4

什麼是可能混淆的是&。這是Python的按位運算符之一。一個很好的後檢查,可以發現[這裏](http://stackoverflow.com/questions/1746613/bitwise-operation-and-usage)。 –

+0

我可以問你在哪裏找到的?我經常在Python中看到按位運算符。 – TigerhawkT3

+3

這與'int'egers的'variable%2 == 0'是一樣的。 – Navith

回答

33

的條件是bitwise operator比較:

>>> 1 & 1 
1 
>>> 0 & 1 
0 
>>> a = 1 
>>> a & 1 == 0 
False 
>>> b = 0 
>>> b & 1 == 0 
True 

由於許多評論說,對於整數這個條件是真對埃文斯和假的可能性。編寫這種流行的方式是if variable % 2 == 0:if not variable % 2:

使用timeit我們可以看到,沒有太大的性能差異。

n & 1("== 0" and "not")

>>> timeit.Timer("bitwiseIsEven(1)", "def bitwiseIsEven(n): return n & 1 == 0").repeat(4, 10**6) 
[0.2037370204925537, 0.20333600044250488, 0.2028651237487793, 0.20192503929138184] 

>>> timeit.Timer("bitwiseIsEven(1)", "def bitwiseIsEven(n): return not n & 1").repeat(4, 10**6) 
[0.18392395973205566, 0.18273091316223145, 0.1830739974975586, 0.18445897102355957] 

n % 2("== 0" and "not")

>>> timeit.Timer("modIsEven(1)", "def modIsEven(n): return n % 2 == 0").repeat(4, 10**6) 
[0.22193098068237305, 0.22170782089233398, 0.21924591064453125, 0.21947598457336426] 

>>> timeit.Timer("modIsEven(1)", "def modIsEven(n): return not n % 2").repeat(4, 10**6) 
[0.20426011085510254, 0.2046220302581787, 0.2040550708770752, 0.2044820785522461] 

重載操作符:

運算符%&都被重載。

按位和運算符超載爲sets.intersection(t)相當於s & t並返回一個「具有s和t共有元素的新集合」。

>>> {1} & {1} 
set([1]) 

這不會影響我們的條件:

>>> def bitwiseIsEven(n): 
... return n & 1 == 0 

>>> bitwiseIsEven('1') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in bitwiseIsEven 
TypeError: unsupported operand type(s) for &: 'str' and 'int' 
>>> bitwiseIsEven({1}) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in bitwiseIsEven 
TypeError: unsupported operand type(s) for &: 'set' and 'int' 

模運算符也將拋出TypeError: unsupported operand type(s)對於大多數非整數。

>>> def modIsEven(n): 
... return n % 2 == 0 

>>> modIsEven({1}) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in modIsEven 
TypeError: unsupported operand type(s) for %: 'set' and 'int' 

它作爲舊的%-formatting的字符串插值運算符過載。如果使用字符串進行比較,則會拋出TypeError: not all arguments converted during string formatting

>>> modIsEven('1') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in modIsEven 
TypeError: not all arguments converted during string formatting 

如果字符串包含有效的轉換說明符,則不會拋出。

>>> modIsEven('%d') 
False 
+15

注意(整數)也很有用,這個技巧會告訴你數字是偶數('True')還是奇數('False')。 – baum

+1

@baum你應該做出答案 - 看起來像你得到它(:btw:afaik&只定義爲整數(和看起來像他們的鴨子) – drevicko

29

此代碼只是檢查,如果基於運算符優先級,這是的variable最低位爲0。:

if (variable & 1) == 0: 

第一和一個(提取只是最低位)的最低位,然後檢查它是否爲0。

14

的&是bitwise operator。它爲其兩個操作數的每一位都返回一個1位的整數,在所有其他位置都爲0。例如:

a = 10 # 0b1010 
b = 6 # 0b0110 
a & b # 0b0010 

現在,如果你有variable & 1,你比較variable0b1這隻會返回1,如果在二進制表示,去年的數字是1,否則0。

6

你唯一值得關注的可能是運營商&。它是一個按位和,它採用兩個操作數的二進制格式,並在每對位執行「邏輯和」。

對於你的榜樣,考慮以下因素:

variable = 2 #0b0010 
if variable & 1 == 0: 
    print "condition satisfied" # satisfied, 0b0010 & 0b0001 = 0 

variable = 5 #0b0101 
if variable & 1 == 0: 
    print "condition satisfied" # not satisfied, 0b0101 & 0b0001 = 1 

注:

variable = 6 #0b0110 
if variable & 2 == 0: 
    print "condition satisfied" # not satisfied, 0b0110 & 0b0010 = 2 (0b0010) 
+1

你的答案有一個錯字,在第一個評論中,你離開了0b0101(5)而不是0b0010(2) – ChristopheLec

+0

@ Majestic12謝謝!我編輯過。 –