Curiosidad sobre __hash__()

Francesc Alted faltet en pytables.org
Vie Feb 6 09:09:39 CET 2009


A Friday 06 February 2009, Chema Cortes escrigué:
> 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.

Ah, no sabía que el hash de objetos de usuario por defecto se pone como 
lo que devuelve id().  Supongo que por eso algunos se confunden y creen 
ése es el comportamiento para todos los objetos.

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

Entonces, si no existe hash para ellos, cómo se hacen las búsquedas?  de 
manera lineal?

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

No entiendo esto último:

In [1]: class A:
   ...:     pass
   ...:

In [2]: a = A()

In [3]: id(a)
Out[3]: 140367942406440

In [4]: hash(a)
Out[4]: 140367942406440

o sea, que parece que sí que es así.  O me pierdo algo?

-- 
Francesc Alted
------------ 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