Curiosidad sobre __hash__()

Chema Cortes py en ch3m4.org
Vie Feb 6 03:13:15 CET 2009


El Thursday 05 February 2009 14:07:20 Francesc Alted escribió:

> A ver, si a y b *son* el mismo objeto ((2,), que no necesariamente es la
> misma dirección de memoria), la hash ha de ser la misma, no?

Umm! Parece que nos estamos liando más de la cuenta.

Se dice que un objeto es "hashable" si:
a) tiene un valor hash que no cambia en toda su vida (método __hash__)
b) se pueden comparar con otros objetos (métodos __eq__ ó __cmp__), de modo 
que si dos objetos tienen el mismo valor, habrán de tener el mismo hash 
(aunque sean de distintos tipos).

Si el hash de un objeto no cumple estas dos reglas, entonces no será válido 
para, por ejemplo, ser índice de diccionarios o de conjuntos.

Si dos tuplas tienen el mismo "valor" --como en el caso de (2,)-- entonces 
deberán tener el mismo hash. Los objetos mutables (listas y diccionarios) no 
son hashables. Los objetos definidos por el usuario, al derivar de la 
clase 'object' adquieren los métodos __hash__ y __cmp__. El primero da la 
dirección de memoria (id()); el segundo siempre da como resultado de la 
comparación como distinto. 

Pero, como ocurre siempre, se pueden hacer algunas trampas :P

#diccionario con hash "subrogado"
class D(dict):
  ID=0
  def __init__(self,**kw):
    dict.__init__(self,**kw)
    self.ID=D.ID
    D.ID+=1
  def __hash__(self):
    return hash(self.ID)


d1=D(a=1,b=2)
print d1,hash(d1)

d2=D(x=123,y=1234)
print d2,hash(d2)

h={d1:"Hola", d2:"Mundo"}
print h


PD Py3k warning: en python3 los objetos definidos por el usuario ya no 
adquieren el método __hash__ por defecto. Se supone que basta con tener los 
métodos __eq__ ó __cmp__ para poder ser índices de diccionarios.

PD2: desconozco porqué el hash de un objeto definido por el usuario no 
coincide con el valor que devuelve la función id(). En toda la documentación 
que he consultado dice que debería ser lo mismo. Supongo que habría que 
estudiar el código.
------------ próxima parte ------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part.
URL: <http://mail.python.org/pipermail/python-es/attachments/20090206/fe9a8b31/attachment.pgp>
------------ próxima parte ------------
_______________________________________________
Lista de correo Python-es 
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes


Más información sobre la lista de distribución Python-es