tuple python
Lista imprimible, pero hashable tupla? (6)
¿ En cómo hash listas? Me dijeron que primero debería convertir a una tupla, por ejemplo, [1,2,3,4,5]
a (1,2,3,4,5)
.
Así que el primero no puede ser hecho un hash, pero el segundo puede. ¿Por qué * ?
* Realmente no estoy buscando una explicación técnica detallada, sino una intuición.
Dado que una lista es mutable, si la modificas también modificarías su hash, lo que arruina el punto de tener un hash (como en un conjunto o una clave de dictado).
Las respuestas son buenas. La razón es la mutabilidad. Si pudiéramos usar listar en dicts como claves; (o cualquier objeto mutable) entonces podríamos cambiar la clave al mutarla (accidental o intencionalmente). Esto causaría un cambio en el valor de hash de la clave en el diccionario debido a que no podríamos rastrear el valor de esa estructura de datos por esa clave. Los valores de hash y las tablas de hash se usan para mapear los datos grandes con facilidad asignándolos a índices que almacenan las entradas de valor real.
Lee más sobre ellos aquí:-
No todas las tuplas son hashables. Por ejemplo, la tupla contiene la lista como un elemento.
x = (1,[2,3])
print(type(x))
print(hash(x))
Podrías hacer que funcione, pero apuesto a que no te gustarían los efectos.
from functools import reduce
from operator import xor
class List(list):
def __hash__(self):
return reduce(xor, self)
Ahora veamos que pasa:
>>> l = List([23,42,99])
>>> hash(l)
94
>>> d = {l: "Hello"}
>>> d[l]
''Hello''
>>> l.append(7)
>>> d
{[23, 42, 99, 7]: ''Hello''}
>>> l
[23, 42, 99, 7]
>>> d[l]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: [23, 42, 99, 7]
Edición: Así que pensé en esto un poco más. Podría hacer que el ejemplo anterior funcione, si devuelve el ID de la lista como su valor hash:
class List(list):
def __hash__(self):
return id(self)
En ese caso, d[l]
te dará ''Hello''
, pero ni d[[23,42,99,7]]
ni d[List([23,42,99,7])]
(porque tú re creando una nueva [Ll]ist
.
Porque las listas son mutables y las tuplas no lo son.
Principalmente, porque las tuplas son inmutables. Supongamos los siguientes trabajos:
>>> l = [1, 2, 3]
>>> t = (1, 2, 3)
>>> x = {l: ''a list'', t: ''a tuple''}
Ahora, ¿qué pasa cuando haces l.append(4)
? ¡Has modificado la clave en tu diccionario! ¡Desde lejos! Si está familiarizado con cómo funcionan los algoritmos de hash, esto debería asustarlo. Las tuplas, por otro lado, son absolutamente inmutables. t += (1,)
puede parecer que está modificando la tupla, pero en realidad no lo es: simplemente está creando una nueva tupla, sin cambiar la clave del diccionario.