¿Qué significa "hashable" en Python?

194

Intenté buscar en Internet pero no pude encontrar el significado de hashable.

¿Cuándo dicen que los objetos son hashableo hashable objectsqué significa?

usuario1755071
fuente
1
Consulte la documentación sobre hashable y el __hash__()método .
26sәɹoɈ
55
que busca objetos hasable o algo así, pero ninguno de los enlaces explica lo que realmente significa
hashable
posible duplicado de Hashable, inmutable
Todos los trabajadores son esenciales

Respuestas:

181

Del glosario de Python :

Un objeto es hashable si tiene un valor hash que nunca cambia durante su vida útil (necesita un __hash__()método) y puede compararse con otros objetos (necesita un método __eq__()o __cmp__()). Los objetos hashables que comparan igual deben tener el mismo valor hash.

Hashability hace que un objeto sea utilizable como clave de diccionario y miembro de conjunto, porque estas estructuras de datos usan el valor hash internamente.

Todos los objetos incorporados inmutables de Python son hashable, mientras que no hay contenedores mutables (como listas o diccionarios). Los objetos que son instancias de clases definidas por el usuario se pueden cambiar de forma predeterminada; todos se comparan desiguales, y su valor hash es suyo id().

NPE
fuente
2
si tiene hash valueahora cuál es el valor hash. ¿Puedes dar algún ejemplo
user1755071
2
@ user55711: Aquí, el valor hash es el resultado de la llamada __hash__(). De manera más general, consulte en.wikipedia.org/wiki/Hash_function
NPE
16
@TorstenBronger: Porque dos objetos desiguales pueden hacer hash con el mismo valor. En otras palabras, el hashing es con pérdida.
NPE
1
En python-2.7.12, el resultado de id(object)es 16x el resultado de object.__hash__(). Por lo tanto, el extracto del glosario es incorrecto para esta versión; el valor hash no lo es id(), pero se deriva de él (como se señaló en los documentos actualizados para python 2.7.12).
davidA
2
Sé que esta es una publicación antigua, pero vale la pena mencionar que la entrada del glosario copiada aquí no es del todo correcta. Puede poner un objeto mutable (como una lista) dentro de una tupla. La tupla sigue siendo inmutable, pero puede cambiar la lista dentro de ella, por lo que no es hashaable. Intenta hash((1, [2, 3]))verlo en acción. He publicado una solicitud para corregir la entrada del glosario para hashable.
John Riehl
102

Todas las respuestas aquí tienen una buena explicación funcional de los objetos hashables en python, pero creo que primero hay que entender el término hashing.

Hashing es un concepto en informática que se utiliza para crear estructuras de datos de acceso pseudoaleatorio de alto rendimiento donde se almacenan y acceden rápidamente grandes cantidades de datos.

Por ejemplo, si tiene 10,000 números de teléfono y desea almacenarlos en una matriz (que es una estructura de datos secuencial que almacena datos en ubicaciones de memoria contiguas y proporciona acceso aleatorio), pero es posible que no tenga la cantidad requerida de datos contiguos ubicaciones de memoria

Por lo tanto, puede usar una matriz de tamaño 100 y una función hash para asignar un conjunto de valores a los mismos índices, y estos valores se pueden almacenar en una lista vinculada. Esto proporciona un rendimiento similar a una matriz.

Ahora, una función hash puede ser tan simple como dividir el número con el tamaño de la matriz y tomar el resto como índice.

Para obtener más detalles, consulte https://en.wikipedia.org/wiki/Hash_function

Aquí hay otra buena referencia: http://interactivepython.org/runestone/static/pythonds/SortSearch/Hashing.html

ojas mohril
fuente
1
Esa es una perspectiva interesante sobre el hash. No lo he pensado de esa manera.
yuvgin
Las tablas hash @yuvgin a menudo se usan para implementar matrices dispersas (es decir, el ejemplo que se proporciona aquí).
Eli Korvigo
@EliKorvigo Me gusta pensar que las matrices regulares son simplemente versiones altamente optimizadas de una tabla hash.
Mark Ransom
1
¿Puedes producir un código simple con respecto al escenario de la matriz de números de teléfono para aclarar el concepto de hash?
Istiaque Ahmed
18

Cualquier cosa que no sea mutable (significa mutable, es probable que cambie) se puede modificar. Además de la función hash para buscar, si una clase la tiene, por ej. dir(tuple)y buscando el __hash__método, aquí hay algunos ejemplos

#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

Lista de tipos inmutables:

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

Lista de tipos mutables:

list, dict, set, bytearray, user-defined classes
usuario1767754
fuente
Recientemente descubrí que Ellipsistambién es un tipo inmutable y puede usarse como clave para a dict.
Gábor Fekete
Incluso se pueden usar clases definidas por el usuario, pero solo sus nombres, no instancias. Por ejemplo:hash(MyClass)
Gábor Fekete el
1
Las instancias @ GáborFekete de clases definidas por el usuario se pueden cambiar si sus clases implementan __hash__y __eq__. Además, todas las clases definidas por el usuario implementan estos métodos (y, por lo tanto, son hash), porque heredan los métodos de object(la clase base universal).
Eli Korvigo
7

Según tengo entendido de acuerdo con el glosario de Python, cuando crea una instancia de objetos que se pueden cambiar, también se calcula un valor inmutable de acuerdo con los miembros o valores de la instancia. Por ejemplo, ese valor podría usarse como clave en un dict como se muestra a continuación:

>>> 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'

podemos encontrar que el valor hash de tuple_a y tuple_c son los mismos ya que tienen los mismos miembros. Cuando usamos tuple_a como la clave en dict_a, podemos encontrar que el valor de dict_a [tuple_c] es el mismo, lo que significa que, cuando se usan como clave en un dict, devuelven el mismo valor porque los valores hash son lo mismo. Para aquellos objetos que no son hashables, el método hash se define como Ninguno:

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

Supongo que este valor hash se calcula sobre la inicialización de la instancia, no de forma dinámica, es por eso que solo los objetos inmutables son hashable. Espero que esto ayude.

Jay.Zhao
fuente
4

Permíteme darte un ejemplo de trabajo para comprender los objetos hashaable en python. Estoy tomando 2 tuplas para este ejemplo. Cada valor en una tupla tiene un valor hash único que nunca cambia durante su vida útil. Entonces, basado en esto tiene valor, se realiza la comparación entre dos tuplas. Podemos obtener el valor hash de un elemento tupla usando Id ().

Comparación entre 2 tuplasEquivalencia entre 2 tuplas

bks4line
fuente
26
esto sería más útil como texto que como imagen
baxx
77
Es una respuesta incorrecta. id () muestra la dirección referenciada en una memoria, no es un valor hash. Para obtener hash, use la función __hash __ (). por ejemplo: t1 .__ hash __ ()
Vlad
@ascentman No dudes en editar una respuesta que creas que es incorrecta. Su edición será revisada por pares y, si se acepta, obtendrá una pequeña recompensa por ello.
XavierStuvw
4

En python significa que el objeto puede ser miembro de conjuntos para devolver un índice. Es decir, tienen una identidad / identificación única.

por ejemplo, en python 3.3:

la estructura de datos Las listas no son hashaable pero la estructura de datos Tuples son hashaable.

Naghceuz
fuente
El hash no es lo mismo que id, que es (aproximadamente) la dirección del objeto en la memoria.
poolie
3

Hashable = capaz de ser hash.

Ok, ¿qué es el hash? Una función hash es una función que toma un objeto, digamos una cadena como "Python", y devuelve un código de tamaño fijo. Por simplicidad, suponga que el valor de retorno es un entero.

Cuando ejecuto hash ('Python') en Python 3, obtengo 5952713340227947791 como resultado. Las diferentes versiones de Python son libres de cambiar la función hash subyacente, por lo que es probable que obtenga un valor diferente. Lo importante es que no importa que muchas veces ejecute hash ('Python'), siempre obtendré el mismo resultado con la misma versión de Python.

Pero el hash ('Java') devuelve 1753925553814008565. Entonces, si el objeto que estoy modificando cambia, también lo hace el resultado. Por otro lado, si el objeto que estoy procesando no cambia, entonces el resultado permanece igual.

¿Por qué importa esto?

Bueno, los diccionarios de Python, por ejemplo, requieren que las claves sean inmutables. Es decir, las claves deben ser objetos que no cambien. Las cadenas son inmutables en Python, al igual que los otros tipos básicos (int, float, bool). Las tuplas y los congelados también son inmutables. Las listas, por otro lado, no son inmutables (es decir, son mutables) porque puede cambiarlas. Del mismo modo, los dictados son mutables.

Entonces, cuando decimos que algo es hashable, queremos decir que es inmutable. Si intento pasar un tipo mutable a la función hash (), fallará:

>>> 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
Sidrah
fuente
1
Tenga en cuenta que python siembra aleatoriamente el algoritmo de hash al comienzo de cada proceso. Por lo tanto, obtendrá valores de hash diferentes si ejecuta hash ('Python') dos veces en diferentes procesos.
D Hudson
2

En Python, cualquier objeto inmutable (como un entero, booleano, cadena, tupla) es hashable, lo que significa que su valor no cambia durante su vida útil. Esto permite a Python crear un valor hash único para identificarlo, que los diccionarios pueden usar para rastrear claves y conjuntos únicos para rastrear valores únicos.

Es por eso que Python requiere que usemos tipos de datos inmutables para las claves en un diccionario.

Akku2403
fuente
-1

Para crear una tabla hash desde cero, todos los valores deben establecerse en "Ninguno" y modificarse una vez que surja un requisito. Los objetos hashables se refieren a los tipos de datos modificables (Diccionario, listas, etc.). Los conjuntos, por otro lado, no se pueden reinicializar una vez asignados, por lo que los conjuntos no se pueden cambiar. Mientras que, la variante de set () - frozenset () - es hashable.

ARRENDAJO
fuente