Confronta se due variabili fanno riferimento allo stesso oggetto in Python


Risposte:


133

Ecco a cosa isserve: x is yrestituisce Truese xe ysono lo stesso oggetto.


6
Nell'esempio, x is zritorna False. Ma se a xez vengono assegnati gli stessi valori invece di elenchi (ad esempio x, z = 13, 13), x is zrestituisce True. Perché?
Bill

12
@ Bill: Questo è un artefatto di come Python gestisce gli int. Python alloca oggetti interi a cui punta xe z. Poiché i piccoli numeri interi sono comuni (-1 come valore di errore, 0 ogni volta che si indicizza effettivamente qualcosa, i piccoli numeri sono di solito valori predefiniti ragionevoli) Python ottimizza preallocando piccoli numeri (da -5 a 256) e riutilizza lo stesso oggetto intero. Quindi il tuo esempio funziona solo per i numeri in questo intervallo. Prova ad assegnare qualcosa di più grande, ad es 270. Per maggiori informazioni guarda qui
ted

1
@AndresR No, è sbagliato. iscontrolla se due nomi fanno riferimento alla stessa posizione di memoria. Non ha nulla a che fare con l'oggetto stesso. È facile avere oggetti immutabili come stringhe uguali ma non archiviate nella stessa posizione, ad esempio ''a'*10000 is 'a' * 10000False.
Jochen Ritzel

1
@JochenRitzel Hai perfettamente ragione, grazie per questo commento! Quindi, non capisco cosa sta succedendo "af" is "af"o () is ()... perché condividono la stessa posizione di memoria?
AndresR

2
@AndreasR Per stringhe / numeri letterali nel codice, il compilatore verifica che esistano solo una volta e li riutilizza. Anche i valori speciali come (), Nessuno, Vero, Falso ecc. Sono definiti come singoli. Durante l'esecuzione il runtime cerca anche di riutilizzare piccoli numeri e stringhe, ma alla fine è un compromesso tra velocità e memoria e ciò che accade dipende da come è stato implementato il runtime di Python.
Jochen Ritzel


11

Mentre le due soluzioni corrette x is ze id(x) == id(z)sono già state pubblicate, voglio sottolineare un dettaglio di implementazione di python. Python memorizza gli interi come oggetti, come ottimizzazione genera un gruppo di piccoli interi all'inizio (da -5 a 256) e punta OGNI variabile che contiene un numero intero con un piccolo valore a questi oggetti preinizializzati. Ulteriori informazioni

Ciò significa che per oggetti interi inizializzati con gli stessi piccoli numeri (da -5 a 256) il controllo se due oggetti sono uguali restituirà true ( ON C-Pyhon , per quanto ne so questo è un dettaglio di implementazione ), mentre per più grandi numeri questo restituisce vero solo se un oggetto viene inizializzato dall'altro.

> i = 13
> j = 13
> i is j
True

> a = 280
> b = 280
> a is b
False

> a = b
> a
280
> a is b
True

python3.6: a = 98765; b = 98765; a è b => True. Qualcosa è cambiato a quanto pare.
Mikhail Kalashnikov

@MikhailKalashnikov No. Ho provato su Python 3.6.2, questo esiste ancora.
nix

esiste ancora su Python 3.7.7
Bill Huang

9

Puoi anche usare id () per controllare a quale oggetto univoco si riferisce ogni nome di variabile.

In [1]: x1, x2 = 'foo', 'foo'

In [2]: x1 == x2
Out[2]: True

In [3]: id(x1), id(x2)
Out[3]: (4509849040, 4509849040)

In [4]: x2 = 'foobar'[0:3]

In [5]: x2
Out[5]: 'foo'

In [6]: x1 == x2
Out[6]: True

In [7]: x1 is x2
Out[7]: False

In [8]: id(x1), id(x2)
Out[8]: (4509849040, 4526514944)

La nota di @ted sull'uso di id è abbastanza rilevante qui.
Leo Ufimtsev


2

Questo è da docs.python.org: "Ogni oggetto ha un'identità, un tipo e un valore. L'identità di un oggetto non cambia mai una volta che è stato creato; potresti pensarlo come l'indirizzo dell'oggetto in memoria. L'operatore 'is' confronta l'identità di due oggetti; la funzione id () restituisce un numero intero che ne rappresenta l'identità. "

Apparentemente ogni volta che cambi il valore l'oggetto viene ricreato come indicato dal cambio di identità. La riga x = 3 seguita dalla riga x = 3.14 non dà errori e fornisce identità, tipi e valori diversi per x.


1
Ottima cattura doc.
prosti
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.