Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

740
Views
En Python, ¿por qué una tupla es hashable pero no una lista?

A continuación, cuando intento hacer hash de una lista, me da un error pero funciona con una tupla. Supongo que tiene algo que ver con la inmutabilidad. ¿Alguien puede explicar esto en detalle?

Lista

 x = [1,2,3] y = {x: 9} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list'

tupla

 z = (5,6) y = {z: 89} print(y) {(5, 6): 89}
over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Los dictados y otros objetos usan hashes para almacenar y recuperar elementos muy rápidamente. La mecánica de todo esto sucede "debajo de las sábanas": usted, como programador, no necesita hacer nada y Python lo maneja todo internamente. La idea básica es que cuando crea un diccionario con {key: value} , Python necesita poder codificar lo que haya usado para la key para que pueda almacenar y buscar el valor rápidamente.

Los objetos inmutables, o los objetos que no se pueden modificar, se pueden modificar. Tienen un único valor único que nunca cambia, por lo que Python puede "hacer hash" de ese valor y usarlo para buscar valores de diccionario de manera eficiente. Los objetos que entran en esta categoría incluyen cadenas, tuplas, enteros, etc. Puede pensar: "¡Pero puedo cambiar una cadena! Simplemente voy a mystr = mystr + 'foo' ", pero de hecho, lo que esto hace es crear una nueva instancia de cadena y la asigna a mystr . No modifica la instancia existente . Los objetos inmutables nunca cambian, por lo que siempre puede estar seguro de que cuando genera un hash para un objeto inmutable, buscar el objeto por su hash siempre devolverá el mismo objeto con el que comenzó, y no una versión modificada.

Puedes probar esto por ti mismo: hash("mystring") , hash(('foo', 'bar')) , hash(1)

Los objetos mutables, o los objetos que se pueden modificar, no se pueden modificar. Una lista se puede modificar en el lugar: mylist.append('bar') o mylist.pop(0) . No puede codificar con seguridad un objeto mutable porque no puede garantizar que el objeto no haya cambiado desde la última vez que lo vio. Encontrará que list , set y otros tipos mutables no tienen un __hash__() . Debido a esto, no puede usar objetos mutables como claves de diccionario:

 >>> hash([1,2,3]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list'

La respuesta de Eric Duminil proporciona un gran ejemplo del comportamiento inesperado que surge del uso de objetos mutables como claves de diccionario.

over 4 years ago · Santiago Trujillo Report

0

Estos son ejemplos de por qué podría no ser una buena idea permitir tipos mutables como claves. Este comportamiento puede ser útil en algunos casos (p. ej., usar el estado del objeto como clave en lugar del objeto en sí ), pero también puede dar lugar a errores o resultados sorprendentes.

Pitón

Es posible usar una lista numérica como clave definiendo __hash__ en una subclase de list :

 class MyList(list): def __hash__(self): return sum(self) my_list = MyList([1, 2, 3]) my_dict = {my_list: 'a'} print(my_dict.get(my_list)) # a my_list[2] = 4 # __hash__() becomes 7 print(next(iter(my_dict))) # [1, 2, 4] print(my_dict.get(my_list)) # None print(my_dict.get(MyList([1,2,3]))) # None my_list[0] = 0 # __hash_() is 6 again, but for different elements print(next(iter(my_dict))) # [0, 2, 4] print(my_dict.get(my_list)) # 'a'

Rubí

En Ruby, está permitido usar una lista como clave. Una lista de Ruby se llama Array y un dict es Hash , pero la sintaxis es muy similar a la de Python:

 my_list = [1] my_hash = { my_list => 'a'} puts my_hash[my_list] #=> 'a'

Pero si se modifica esta lista, el dict ya no encuentra el valor correspondiente, incluso si la clave todavía está en el dict:

 my_list << 2 puts my_list #=> [1,2] puts my_hash.keys.first #=> [1,2] puts my_hash[my_list] #=> nil

Es posible forzar el dictado para calcular los hashes de clave nuevamente:

 my_hash.rehash puts my_hash[my_list] #=> 'a'
over 4 years ago · Santiago Trujillo Report

0

Un hashset calcula el hash de un objeto y, en función de ese hash, almacena el objeto en la estructura para una búsqueda rápida. Como resultado, por contrato, una vez que se agrega un objeto al diccionario, el hash no puede cambiar . La mayoría de las buenas funciones hash dependerán de la cantidad de elementos y de los elementos en sí.

Una tupla es inmutable , por lo que después de la construcción, los valores no pueden cambiar y, por lo tanto, el hash tampoco puede cambiar (o al menos una buena implementación no debería permitir que el hash cambie).

Una lista, por otro lado, es mutable : luego se pueden agregar/eliminar/alterar elementos. Como resultado, el hash puede cambiar violando el contrato.

Entonces, todos los objetos que no pueden garantizar una función hash que permanezca estable después de agregar el objeto, violan el contrato y, por lo tanto, no son buenos candidatos. Porque para una búsqueda , el diccionario primero calculará el hash de la clave y determinará el cubo correcto. Si mientras tanto se cambia la clave, esto podría generar falsos negativos: el objeto está en el diccionario, pero ya no se puede recuperar porque el hash es diferente, por lo que se buscará en un cubo diferente al que se agregó originalmente. .

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!