2013-05-26 7 views
5

Quando si utilizza un dizionario in Python, il seguente è impossibile:Perché l'hash Python non elenca l'ID?

d = {} 
d[[1,2,3]] = 4 

dal 'list' is an unhashable type. Tuttavia, la funzione id in Python restituisce un numero intero per un oggetto che è garantito essere univoco per la durata dell'oggetto.

Perché Python non usa id per eseguire l'hash di un dizionario? Ci sono degli svantaggi?

risposta

11

Il motivo è proprio qui (Why must dictionary keys be immutable)

alcune soluzioni non accettabili che sono state proposte:

  • liste di hash per il loro indirizzo (ID oggetto). Questo non funziona perché se si costruisce una nuova lista con lo stesso valore non verrà trovata; es .:

    mydict = {[1, 2]: '12'}

    print mydict[[1, 2]]

solleverebbe un'eccezione KeyError perché l'ID della [1, 2] utilizzato nella seconda linea differisce da quello nella prima riga. In altre parole, le chiavi del dizionario dovrebbero essere confrontate usando ==, non usando is.

+0

Ah, grazie - questo è quello che stavo cercando. – sdasdadas

+0

...e se tu * fai * vuoi l'hashing con id, per qualche ragione, puoi fare esattamente questo. – Elazar

5

È un requisito che se a == b, quindi hash(a) == hash(b). L'utilizzo di id può interromperlo, poiché l'ID non cambierà se si modifica l'elenco. Quindi potresti avere due liste con contenuti uguali, ma con hash diversi.

Un altro modo per vederlo è, sì, lo si potrebbe fare, ma significherebbe che non è possibile recuperare il valore di dict con un'altra lista con lo stesso contenuto. È possibile recuperarlo solo utilizzando lo stesso identico oggetto elenco della chiave.

0

Nei dizionari Python le chiavi vengono confrontate utilizzando == e l'operatore di uguaglianza con le liste esegue un controllo di uguaglianza articolo per articolo in modo che due elenchi diversi con gli stessi elementi siano uguali e si comportino come la stessa chiave in un dizionario.

Se è necessario mantenere un dizionario o una serie di elenchi per identità anziché per uguaglianza, è sufficiente racchiudere l'elenco in un oggetto definito dall'utente oppure, in base al contesto, è possibile utilizzare un dizionario in cui sono memorizzati gli elementi/recuperare utilizzando id in modo esplicito.

Nota, tuttavia, che mantenendo la id di un oggetto memorizzato non implica l'oggetto rimarrà vivo, che non v'è alcun modo per andare da id di opporsi e che id può essere riutilizzato nel tempo per gli oggetti che sono stati raccolti rifiuti . Una soluzione è quella di utilizzare

my_dict[id(x)] = [x, value] 

invece di

my_dict[id(x)] = value 
Problemi correlati