2013-08-16 11 views
6

Ero (forse erroneamente) pensando che l'operatore is esegua il confronto id().Cosa fa l'operatore 'is' in Python?

>>> x = 10 
>>> y = 10 
>>> id(x) 
1815480092 
>>> id(y) 
1815480092 
>>> x is y 
True 

Tuttavia, con val is not None, sembra che non sia così semplice.

>>> id(not None) 
2001680 
>>> id(None) 
2053536 
>>> val = 10 
>>> id(val) 
1815480092 
>>> val is not None 
True 

Quindi, cosa fa l'operatore 'is'? E 'solo il confronto tra gli oggetti che ho appena congetturato? In tal caso, val is not None viene interpretato in Python come not (val is None)?

+0

Sì, 'val is not None' e' not (val is None) 'sono [equivalenti] (http://stackoverflow.com/questions/12941287/does-not-e-in-c-differ-da -e-not-in-c-in-python). Ma il primo è più leggibile IMO. –

risposta

10

Hai perso che is not è un operatore anche.

Senza is, il regolare not operatore in ritorna un valore booleano:

>>> not None 
True 

not None è quindi il 'valore' booleano inverso di None. In un contesto booleano None è falso:

>>> bool(None) 
False 

così not None è booleano True.

Sia None e True sono oggetti troppo, ed entrambi hanno un indirizzo di memoria (il valore id() ritorni per l'attuazione CPython di Python):

>>> id(True) 
4440103488 
>>> id(not None) 
4440103488 
>>> id(None) 
4440184448 

is test se due riferimenti sono indicando lo stesso oggetto; se qualcosa è lo stesso oggetto, avrà lo stesso id(). is restituisce un valore booleano, True o False.

is not è l'inverso dell'operatore is. È l'equivalente di not (op1 is op2), in un solo operatore. Dovrebbe Non essere letto come op1 is (not op2) qui:

>>> 1 is not None  # is 1 a different object from None? 
True 
>>> 1 is (not None) # is 1 the same object as True? 
False 
+0

È importante ricordare che 'is not' è un operatore singolo. 'True is (not 1) -> False',' True non è 1 -> True'. Quindi ciò che 'non None' restituisce è irrilevante. –

+0

@PavelAnossov Il valore di ritorno di 'not None' è rilevante perché OP ha usato' (not None) 'in un esempio. – delnan

+0

@delnan: esattamente, perché apparentemente l'OP ha mancato che 'is not' sia un operatore singolo. Sembra che sia stato previsto 'op1 is (not None)'. Quale sarebbe 'False', non' True'. –

3

A complemento Martijn Pieters risposta, None, True e False sono single. V'è una sola istanza di ciascuno di questi valori in modo da è sicuro da usare is per testare loro ..

>>> id(True) 
8851952 
>>> id(False) 
8851920 
>>> id(None) 
8559264 
>>> id(not None) 
8851952 
>>> id(1 == 0) 
8851920 
>>> id(1 == 1) 
8851952 
+0

Per 'None' Sono d'accordo, per' False' e ​​'True' potrebbe essere un dettaglio di implementazione. Tuttavia, testare 'se xxx è True:' mi sembra stupido; un semplice 'se xxx:' dovrebbe essere migliore. – glglgl

+0

@glglgl Sono d'accordo. Ho appena introdotto 'True' e' False' nella discussione poichè la domanda originale menzionata 'is (not None)'. Cioè, usando l'operatore 'is' per confrontare con il valore booleano' (non None) '- che non è lo stesso che usare l'operatore' is not' come spiegato in altri commenti. –

+0

@glglgl si può facilmente arrivare con un caso patologico per 'xxx is True': codici di errore restituiti, alla maniera dei processi linux. Se una funzione ha successo, restituisce True, se fallisce, restituisce un codice di errore, che può essere maggiore di 0, e quindi dovrebbe anche valutare true. Certo, ci sono molti modi migliori per farlo, ma qui siamo patologici. (Certo, quanto sopra ha più senso per un lettore del necessario 'se! Risultato:' con linux-esque zero-for-success.) – RoadieRich

0

Python cerca di emulare la sintassi del linguaggio inglese per renderlo più leggibile, ma in questo caso l'operatore la precedenza è un po 'confusa.

>>> val is not None 
True 

In inglese, si chiedono se val non ha un valore che è rappresentato dallo stesso oggetto come None. Nell'esempio sopra riportato, val=10, la risposta è (correttamente) True.

Tuttavia, da una logica, punto di vista sintattico avete rotto verso il basso la dichiarazione parola per parola e assunto che sia:

>>> val is (not None) 
False 

che, una volta racchiuso in patentheses appropriati, riporta il risultato atteso (False).

Come @Martijn Pieters sottolinea, is notis an operator in its own right, ed è l'unico operatore al lavoro qui.

Se si voleva scrivere come una dichiarazione non ambigua utilizzando solo gli operatori che non contengono spazi, si potrebbe scrivere:

>>> not (val is None) 
True 

ma che non è come si dovrebbe 'dire' la dichiarazione prevista in inglese, o possibilmente anche scriverlo in pseudo-codice.