2014-09-15 5 views
10

I risultati del codice sottostante in Python 2.7 mi hanno colpito come una contraddizione. L'operatore is dovrebbe funzionare con l'identità dell'oggetto e quindi è id. Ma i loro risultati divergono quando guardo un metodo definito dall'utente. Perché?Funzione `id` in Python 2.7, operatore` is`, identità dell'oggetto e metodi definiti dall'utente

py-mach >>class Hello(object): 
... def hello(): 
... pass 
... 
py-mach >>Hello.hello is Hello.hello 
False 
py-mach >>id(Hello.hello) - id(Hello.hello) 
0 

Ho trovato il seguente estratto dalla descrizione del Python data model alquanto utile. Ma non ha davvero chiarito tutto. Perché la funzione id restituisce lo stesso numero intero se gli oggetti metodo definiti dall'utente vengono ricostruiti ogni volta?

oggetti metodo definito dall'utente possono essere creati quando ottiene un attributo di una classe (forse tramite un'istanza di quella classe), se questo attributo è un oggetto funzione definita dall'utente, un metodo di oggetto definito dall'utente non associato, o un oggetto metodo di classe. Quando l'attributo è un oggetto metodo definito dall'utente, un nuovo oggetto metodo viene creato solo se la classe da cui viene richiamato è uguale o una classe derivata della classe memorizzata nell'oggetto metodo originale; in caso contrario, l'oggetto metodo originale viene utilizzato così com'è.

+0

@ user2357112 - Penso che OP capisca quella parte "Perché la funzione' id' restituisce lo stesso numero intero se gli oggetti metodo definiti dall'utente vengono ricostruiti ogni volta? ". Un dupe migliore sarebbe http://stackoverflow.com/q/3877230/748858 – mgilson

+0

@mgilson: Sì, è per questo che ho riaperto. Devo smettere di usare il dupehammer così in fretta. – user2357112

+0

@ user2357112 - Mi è piaciuto molto di più nel giorno in cui sono richieste altre 4 persone per essere d'accordo con me che era un vero capriccio - In questi giorni sono più riluttante a mettere giù il dupehammer ... – mgilson

risposta

18

La documentazione Python per i id function stati:

Ritorna la "identità" di un oggetto. Questo è un intero (o un intero lungo) che è garantito essere unico e costante per questo oggetto durante la sua vita. Due oggetti con vite non sovrapposte possono avere lo stesso valore id().

(sottolineatura mia)

Quando si esegue id(Hello.hello) == id(Hello.hello), l'oggetto metodo viene creato solo per breve tempo ed è considerato "morto" dopo la prima chiamata a 'id'. A causa della chiamata a id, è sufficiente che lo Hello.hello sia attivo per un breve periodo di tempo, sufficiente per ottenere l'id. Una volta ottenuto l'id, l'oggetto è morto e il secondo Hello.hello può riutilizzare quell'indirizzo, che lo fa apparire come se i due oggetti avessero lo stesso id.

Questo è in contrasto con fare Hello.hello is Hello.hello - entrambe le istanze devono vivere abbastanza a lungo da essere confrontati tra loro, quindi si finisce per avere due istanze dal vivo.

Se invece provato:

>>> a = Hello.hello 
>>> b = Hello.hello 
>>> id(a) == id(b) 
False 

... si otterrebbe il valore atteso di False.

+1

In teoria ' Hello.hello è Hello.hello' potrebbe cancellare il suo riferimento del primo 'Hello.hello' prima di chiedere il secondo per il suo' id'. – Veedrac

8

Questa è una conseguenza "semplice" di come funziona l'allocatore di memoria. E 'molto simile al caso:

>>> id([]) == id([]) 
True 

Fondamentalmente pitone non garantisce che l'identificativo del non ottengono riutilizzati - garantisce solo che l'ID è unico fino a quando l'oggetto è vivo. In questo caso, il primo oggetto passato a id è morto dopo la chiamata a id e (C) python riutilizza tale id durante la creazione del secondo oggetto.

mai fare affidamento su questo comportamento in quanto è ammessi dal riferimento di lingua, ma certamente non richiesto.