Cosa significa "hash" in Python?


194

Ho provato a cercare su Internet ma non sono riuscito a trovare il significato di hash.

Quando dicono che gli oggetti sono hashableo hashable objectscosa significano?


1
Consulta la documentazione su hash e il __hash__()metodo .
ʇsәɹoɈ,

5
che cerca oggetti hasable o qualcosa del genere, ma nessuno dei link spiega cosa significhi effettivamente
hash

Risposte:


181

Dal glossario di Python :

Un oggetto è hash se ha un valore hash che non cambia mai durante il suo ciclo di vita (ha bisogno di un __hash__()metodo) e può essere confrontato con altri oggetti (ha bisogno di un metodo __eq__()o __cmp__()). Gli oggetti hash che si equivalgono devono avere lo stesso valore hash.

La hashability rende un oggetto utilizzabile come chiave di dizionario e membro set, poiché queste strutture di dati utilizzano internamente il valore di hash.

Tutti gli oggetti incorporati immutabili di Python sono hash, mentre non esistono contenitori mutabili (come elenchi o dizionari). Gli oggetti che sono istanze di classi definite dall'utente sono hash per impostazione predefinita; si confrontano tutti in modo diseguale e il loro valore di hash è il loro id().


2
se ha hash valueora qual è il valore di hash. puoi fare qualche esempio
user1755071 del

2
@ user55711: qui, il valore hash è il risultato della chiamata __hash__(). Più in generale, vedi en.wikipedia.org/wiki/Hash_function
NPE

16
@TorstenBronger: Perché due oggetti disuguali possono eseguire l'hash sullo stesso valore. In altre parole, l'hashing è in perdita.
NPE,

1
In python-2.7.12, il risultato di id(object)è 16x il risultato di object.__hash__(). Quindi l'estratto di glossario non è corretto per questa versione - il valore di hash non id()lo è, ma ne deriva (come notato nei documenti aggiornati per Python 2.7.12).
David,

2
So che questo è un vecchio post, ma vale la pena ricordare che la voce del glossario copiata qui non è del tutto corretta. Puoi mettere un oggetto mutevole (come un elenco) all'interno di una tupla. La tupla è ancora immutabile, ma è possibile modificare l'elenco al suo interno, quindi non è hash. Prova hash((1, [2, 3]))a vederlo in azione. Ho pubblicato una richiesta per correggere la voce del glossario per hash.
John Riehl,

102

Tutte le risposte qui hanno una buona spiegazione funzionante degli oggetti hash in Python, ma credo che si debba prima capire il termine Hashing.

L'hashing è un concetto di informatica che viene utilizzato per creare strutture di dati ad accesso pseudo casuale ad alte prestazioni in cui è necessario archiviare e accedere rapidamente a grandi quantità di dati.

Ad esempio, se si dispone di 10.000 numeri di telefono e si desidera archiviarli in un array (che è una struttura di dati sequenziale che archivia i dati in posizioni di memoria contigue e fornisce accesso casuale), ma è possibile che non si disponga della quantità richiesta di contigua posizioni di memoria.

Pertanto, puoi invece utilizzare un array di dimensioni 100 e utilizzare una funzione hash per mappare un set di valori sugli stessi indici e questi valori possono essere memorizzati in un elenco collegato. Ciò fornisce prestazioni simili a un array.

Ora, una funzione di hash può essere semplice come dividere il numero con la dimensione dell'array e prendere il resto come indice.

Per maggiori dettagli, consultare https://en.wikipedia.org/wiki/Hash_function

Ecco un altro buon riferimento: http://interactivepython.org/runestone/static/pythonds/SortSearch/Hashing.html


1
Questa è una prospettiva interessante sull'hash. Non ci ho pensato in quel modo.
yuvgin,

Le tabelle hash @yuvgin vengono spesso utilizzate per implementare array sparsi (ovvero l'esempio fornito qui).
Eli Korvigo,

@EliKorvigo Mi piace pensare agli array regolari semplicemente come versioni altamente ottimizzate di una tabella hash.
Mark Ransom,

1
puoi produrre qualche semplice codice relativo allo scenario dell'array di numeri di telefono per chiarire il concetto di hashing?
Istiaque Ahmed, il

18

Tutto ciò che non è mutabile (mezzi mutabili, suscettibili di cambiare) può essere sottoposto a hash. Oltre alla funzione hash da cercare, se una classe ce l'ha, ad es. dir(tuple)e cercando il __hash__metodo, ecco alcuni esempi

#x = hash(set([1,2])) #set unhashable
x = hash(frozenset([1,2])) #hashable
#x = hash(([1,2], [2,3])) #tuple of mutable objects, unhashable
x = hash((1,2,3)) #tuple of immutable objects, hashable
#x = hash()
#x = hash({1,2}) #list of mutable objects, unhashable
#x = hash([1,2,3]) #list of immutable objects, unhashable

Elenco di tipi immutabili:

int, float, decimal, complex, bool, string, tuple, range, frozenset, bytes

Elenco di tipi mutabili:

list, dict, set, bytearray, user-defined classes

Recentemente ho scoperto che Ellipsisè anche un tipo immutabile e può essere usato come chiave per a dict.
Gábor Fekete,

È possibile utilizzare anche le classi definite dall'utente ma solo i loro nomi non le istanze. Ad esempio:hash(MyClass)
Gábor Fekete,

1
Le istanze di @ GáborFekete di classi definite dall'utente sono hash se le loro classi implementano __hash__e __eq__. Inoltre, tutte le classi definite dall'utente implementano questi metodi (e quindi sono hash), perché ereditano i metodi dalla object(classe base universale).
Eli Korvigo,

7

Secondo la mia comprensione secondo il glossario di Python, quando si crea un'istanza di oggetti che sono hash, viene anche calcolato un valore immutabile in base ai membri o ai valori dell'istanza. Ad esempio, quel valore potrebbe quindi essere utilizzato come chiave in un dict come di seguito:

>>> tuple_a = (1,2,3)
>>> tuple_a.__hash__()
2528502973977326415
>>> tuple_b = (2,3,4)
>>> tuple_b.__hash__()
3789705017596477050
>>> tuple_c = (1,2,3)
>>> tuple_c.__hash__()
2528502973977326415
>>> id(a) == id(c)  # a and c same object?
False
>>> a.__hash__() == c.__hash__()  # a and c same value?
True
>>> dict_a = {}
>>> dict_a[tuple_a] = 'hiahia'
>>> dict_a[tuple_c]
'hiahia'

possiamo scoprire che il valore di hash di tuple_a e tuple_c sono gli stessi poiché hanno gli stessi membri. Quando usiamo tuple_a come chiave in dict_a, possiamo scoprire che il valore per dict_a [tuple_c] è lo stesso, il che significa che, quando vengono utilizzati come chiave in un dict, restituiscono lo stesso valore perché i valori hash sono lo stesso. Per quegli oggetti che non sono hash, il metodo hash è definito come Nessuno:

>>> type(dict.__hash__) 
<class 'NoneType'>

Immagino che questo valore di hash sia calcolato sull'inizializzazione dell'istanza, non in modo dinamico, ecco perché solo gli oggetti immutabili sono hash. Spero che questo ti aiuti.


4

Lascia che ti dia un esempio funzionante per comprendere gli oggetti hash in Python. Sto prendendo 2 tuple per questo esempio. Ogni valore in una tupla ha un valore hash univoco che non cambia mai durante la sua vita. Quindi sulla base di questo ha valore, viene fatto il confronto tra due tuple. Possiamo ottenere il valore hash di un elemento tupla usando Id ().

Confronto tra 2 tupleEquivalenza tra 2 tuple


26
questo sarebbe più utile come testo piuttosto che come immagine
baxx,

7
è una risposta sbagliata. id () mostra l'indirizzo di riferimento in una memoria, non è un valore di hash. Per ottenere l'hash usa la funzione __hash __ (). ad esempio: t1 .__ hash __ ()
Vlad

@ascentman Non esitare a modificare una risposta che ritieni errata. La modifica sarà sottoposta a peer review e, se accettata, riceverai un piccolo punteggio per questo.
XavierStuvw,

4

In Python significa che l'oggetto può essere membro di insiemi per restituire un indice. Cioè, hanno identità / ID univoci.

ad esempio, in Python 3.3:

la struttura dei dati Gli elenchi non sono eseguibili ma la struttura dei dati Le tuple sono eseguibili.


L'hash non è lo stesso di id, che è (approssimativamente) l'indirizzo dell'oggetto in memoria.
poolie,

3

Hashable = capace di essere hash.

Ok, cos'è l'hashing? Una funzione di hashing è una funzione che accetta un oggetto, ad esempio una stringa come "Python" e restituisce un codice di dimensioni fisse. Per semplicità, supponiamo che il valore restituito sia un numero intero.

Quando eseguo hash ('Python') in Python 3, ottengo 5952713340227947791 come risultato. Diverse versioni di Python sono libere di modificare la funzione hash sottostante, quindi probabilmente otterrai un valore diverso. L'importante è che non importa ora che eseguo hash ('Python'), otterrò sempre lo stesso risultato con la stessa versione di Python.

Ma hash ('Java') restituisce 1753925553814008565. Quindi se l'oggetto che sto eseguendo l'hashing cambia, anche il risultato cambia. D'altra parte, se l'oggetto con cui sto eseguendo il hashing non cambia, il risultato rimane lo stesso.

Perché è importante?

Bene, i dizionari Python, per esempio, richiedono che le chiavi siano immutabili. Cioè, le chiavi devono essere oggetti che non cambiano. Le stringhe sono immutabili in Python, così come gli altri tipi di base (int, float, bool). Anche le tuple e i frozenset sono immutabili. Le liste, d'altra parte, non sono immutabili (cioè sono mutabili) perché puoi cambiarle. Allo stesso modo, i dadi sono mutabili.

Quindi, quando diciamo che qualcosa è seccabile, intendiamo che è immutabile. Se provo a passare un tipo mutabile alla funzione hash (), fallirà:

>>> hash('Python')
1687380313081734297
>>> hash('Java')
1753925553814008565
>>>
>>> hash([1, 2])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash({1, 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> hash({1 : 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>>
>>> hash(frozenset({1, 2}))
-1834016341293975159
>>> hash((1, 2))
3713081631934410656

1
Nota che Python esegue il seeding casuale dell'algoritmo di hashing all'inizio di ogni processo. Pertanto, otterrai effettivamente valori hash diversi se esegui hash ('Python') due volte in processi diversi.
D Hudson,

2

In Python, qualsiasi oggetto immutabile (come un numero intero, un valore booleano, una stringa, una tupla) è hash, il che significa che il suo valore non cambia durante la sua vita. Ciò consente a Python di creare un valore hash univoco per identificarlo, che può essere utilizzato dai dizionari per tenere traccia di chiavi e set univoci per tenere traccia di valori univoci.

Questo è il motivo per cui Python ci richiede di utilizzare tipi di dati immutabili per le chiavi in ​​un dizionario.


-1

Per creare una tabella di hashing da zero, tutti i valori devono essere impostati su "Nessuno" e modificati una volta che si presenta un requisito. Gli oggetti hashable si riferiscono ai tipi di dati modificabili (dizionario, elenchi ecc.). D'altra parte, i set non possono essere reinizializzati una volta assegnati, quindi i set non sono cancellabili. Considerando che, La variante di set () - frozenset () - è hash.

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.