2010-04-05 20 views

risposta

40

x is y è diverso da x == y.

x is y vale se e solo se id(x) == id(y) - cioè x e y devono essere uno stesso oggetto (con gli stessi id s).

Per tutti gli oggetti Python incorporati (come stringhe, elenchi, dit, funzioni, ecc.), Se x is y, quindi x == y è anche True. Tuttavia, questo non è garantito in generale. A rigor di termini, x == y è true se e solo se x.__eq__(y) restituisce True.

È possibile definire un oggetto x con un metodo __eq__ che restituisce sempre False, per esempio, e ciò causerebbe x == y restituisca false, anche se x is y.

Quindi la riga di fondo è, x is y e x == y sono test completamente diversi.

considerare questo per esempio:

In [1]: 0 is False 
Out[1]: False 

In [2]: 0 == False 
Out[2]: True 

PS. Invece di

if x is y: 
    return True 
else: 
    return False 

è più Pythonic scrivere

return x is y 

E allo stesso modo,

if x == y: 
    return True 
else: 
    return False 

possono essere sostituiti con

return x == y 
+0

Questo è stato davvero utile. Grazie! – ensnare

+0

@ensnare: Nessun problema! Sono contento di poterti aiutare. – unutbu

+7

Sono un po 'schizzinoso, ma non è corretto che sia necessario 'x == y' per essere vero prima che' x is y' possa essere vero. Sono test indipendenti. In pratica, in pratica, ti viene difficile trovare un controesempio ragionevole, ma il metodo speciale '__eq__' potrebbe solo restituire' False' o generare un'eccezione. –

4

Dipende. is e is not fare confronto di identità, che è buono per None, Ellipsis, o assicurandosi che due oggetti siano gli stessi. Altrimenti, utilizzare == o !=.

15

x is y a confronto le identità dei due oggetti , e sta chiedendo 'sono x e nomi diversi per lo stesso oggetto?' È equivalente a id(x) == id(y).

x == y utilizza l'operatore di uguaglianza e pone la domanda più sciolto 'sono x e y uguali?' Per i tipi definiti dall'utente è equivalente a x.__eq__(y).

Il metodo speciale __eq__ dovrebbe rappresentare "equità" per gli oggetti, ad esempio una classe che rappresenta le frazioni vorrebbe 1/2 uguale a 2/4, anche se l'oggetto "a metà" non può avere la stessa identità di l'oggetto "due quarti".

Si noti che non è solo il caso che a == b non implichi a is b, ma anche il contrario è vero. Uno non è in generale un requisito più rigoroso rispetto all'altro. Sì, questo significa che si può avere a == a ritorno False se davvero si vuole, ad esempio:

>>> a = float('nan') 
>>> a is a 
True 
>>> a == a 
False 

In pratica se is è quasi sempre un confronto più specifico di ==.

+6

L'esempio delle frazioni è davvero sul posto, Great Scott. :) – tzot

9
  • == e != sono oggetto valore operatori di confronto
  • is e is not sono oggetto identità operatori di confronto

come gli altri hanno già detto, is (e is not) sono solo quando effettivamente cura che una coppia di variabili riferiamo esattamente lo stesso oggetto. nella maggior parte dei casi, non ti interessa affatto, quindi useresti == e !=.

tuttavia, ciò che si può iniziare a notare, se si guarda a un sacco di codice Python, è che is (e is not) hanno maggiori probabilità di essere usato quando si confrontano contro True, False e None. la ragione principale di ciò è che quegli oggetti sono singoletti, il che significa che esiste esattamente un'istanza di ciascuno di questi valori. perché importa? bene, questo porta ad un altro motivo ... velocità.

con == e !=, l'interprete deve tirare su entrambi gli oggetti di cui, al fine di effettuare un confronto (dal fatto che siano o meno lo stesso), mentre is e is not semplicemente controlla i valori degli oggetti a cui si riferiscono. con questo detto, puoi vedere che quest'ultima coppia si esibirà più velocemente perché non devi recuperare gli oggetti stessi per fare il confronto. Ecco un test di velocità di un paio di anni fa, dove abbiamo concluso che per una tantum, non è un grosso problema, ma se si chiama un gazillion times in un circuito chiuso, beh, inizierà a sommarsi.

http://mail.python.org/pipermail/tutor/2008-June/062708.html

linea di fondo è che è possibile utilizzare i confronti oggetto di identità per la verifica contro True, False e None, e tutto il resto dovrebbe usare operatori di uguaglianza straight-up. non entreremo in interi interni né metodi di istanza associati, o qualcosa del genere qui. :-)

+0

Buon punto sul confronto con i singleton. Per quanto riguarda la velocità, vale la pena notare che 'if a == True:' è più lento di 'if a is True:' che a sua volta è più lento di 'if a:' (almeno per i tipi predefiniti nei miei test). Spesso usare solo 'a' o' not a' è l'opzione più veloce sebbene non siano semanticamente uguali a 'a is True' o' a is None' ecc. –

+0

Quindi, per quanto riguarda il confronto di ints, come '1 è 1' o '1 == 1'? –

+0

anche se sono entrambi equivalenti quando si usano piccoli valori (attualmente) nell'intervallo '(-5, 256)', quelli non sono numeri pubblicizzati e possono cambiare in qualsiasi versione, quindi è più sicuro usare solo '==' in tutto casi tranne "Nessuno", "Vero" e "Falso" (e forse alcuni altri). – wescpy

Problemi correlati