2015-04-16 9 views
24

Ho trovato questo strano if -affermazione nel codice di qualcun altro:Strano if

if variable & 1 == 0: 

io non lo capisco. Dovrebbe avere due ==, giusto?

Qualcuno può spiegarlo?

+4

quello che probabilmente è fonte di confusione è il &. Questo è uno degli operatori bit a bit di Python. Un buon post che può essere esaminato [qui] (http://stackoverflow.com/questions/1746613/bitwise-operation-and-usage). –

+0

Posso chiederti dove l'hai trovato? Non vedo spesso operatori bit a bit in Python. – TigerhawkT3

+3

È uguale a 'variable% 2 == 0' per' int'egers. – Navith

risposta

33

Il condizionale è un confronto bitwise operator:

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

Come molti dei commenti dicono, per gli interi questo condizionale è vero per livella e False per probabilità. Il modo più diffuso di scrivere questo è if variable % 2 == 0: o if not variable % 2:

Usando timeit possiamo vedere che non c'è molta differenza in termini di prestazioni.

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] 

Operatori di overload:

Entrambi gli operatori % e & sono sovraccarichi.

Il bit per bit e l'operatore sono sovraccarichi per set. s.intersection(t) equivale a s & t e restituisce un "nuovo set con elementi comuni a se t".

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

Questo non influenza il nostro condizionale:

>>> 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' 

L'operatore modulo sarà anche buttare TypeError: unsupported operand type(s) per la maggior parte dei non-int.

>>> 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' 

di sovraccarico come operatore di interpolazione di stringhe per il vecchio %-formatting. Getta TypeError: not all arguments converted during string formatting se una stringa viene utilizzata per il confronto.

>>> 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 

Questo non verrà generato se la stringa include un identificatore di conversione valido.

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

È anche utile notare che (per i numeri interi), questo trucco ti dirà se il numero è pari ('Vero') o dispari (' Falso'). – baum

+1

@baum dovresti fare una risposta - sembra che tu abbia capito (: btw: afaik e viene definito solo per numeri interi (e anatre che sembrano come loro;) – drevicko

29

Questo codice solo controlla se il bit più basso di variable è uno 0. Sulla base di precedenza degli operatori questo è:

if (variable & 1) == 0: 

primo e il bit più basso con uno (estratto solo il bit più basso), quindi controlla se è 0.

14

Il & è un bitwise operator. Restituisce un intero con 1 bit per ogni bit dei suoi due operandi che sono entrambi 1 e 0 in tutti gli altri luoghi. Per esempio:

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

Ora, se avete variable & 1, si sta confrontando variable contro 0b1 che restituirà solamente 1, se tale ultima cifra nella rappresentazione binaria è un 1, altrimenti 0.

6

tuo l'unica preoccupazione è probabilmente l'operatore &. È un bit a bit e che accetta il formato binario dei due operandi ed esegue "logica e" su ogni coppia di bit.

Per esempio, si consideri il seguente:

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 

Nota:

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

C'è un errore di battitura nella tua risposta, nel primo se commento, hai lasciato 0b0101 (5) invece di 0b0010 (2) – ChristopheLec

+0

@ Majestic12 Grazie! Ho modificato. –