Pregunta

Yo tenía un extraño error al trasladar una función de Python 3.1 de la horquilla de mi programa.Yo se redujo a la siguiente hipótesis:

En contraste con Python 2.x, en Python 3.x si un objeto tiene una __eq__ el método es automáticamente unhashable.

¿Es esto cierto?

Esto es lo que sucede en Python 3.1:

>>> class O(object):
...     def __eq__(self, other):
...         return 'whatever'
...
>>> o = O()
>>> d = {o: 0}
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    d = {o: 0}
TypeError: unhashable type: 'O'

La pregunta es, ¿cómo puedo resolver mi problema personal?Tengo un objeto ChangeTracker que almacena un WeakKeyDictionary que apunta a varios objetos, indicando para cada uno el valor de sus pepinillos volcado en un cierto punto del tiempo en el pasado.Siempre que un objeto existente es comprobar en el rastreador de cambio, dice que la nueva solución de limpieza química es idéntica a la de su antiguo y, por lo tanto decir si el objeto ha cambiado en el ínterin.El problema es que ahora ni siquiera puedo comprobar si el objeto dado en la biblioteca, debido a que hace elevar una excepción sobre el objeto que se unhashable.(Causa tiene un __eq__ método). ¿Cómo puedo evitar esto?

¿Fue útil?

Solución

Sí, si define __eq__, el valor predeterminado __hash__ (es decir, cifrar la dirección del objeto en la memoria) desaparece. Esto es importante porque el hash debe ser coherente con la igualdad: los objetos iguales deben ser el mismo.

La solución es simple: simplemente defina <=> junto con la definición de <=>.

Otros consejos

Este párrafo de http://docs.python.org/3.1 /reference/datamodel.html#object.hash

  

Si una clase que anula __eq__()   necesita retener la implementación de   __hash__() de una clase principal, se debe decir al intérprete esto   explícitamente configurando __hash__ = <ParentClass>.__hash__. De lo contrario el   la herencia de __hash__ será   bloqueado, como si <=> hubiera sido   establecido explícitamente en Ninguno.

Compruebe el Python 3 manual de object.__hash__:

Si una clase no define un __eq__() el método no debe definir un __hash__() operación; si se define __eq__() pero no __hash__(), sus instancias no podrán ser utilizados como elementos de hashable colecciones.

El énfasis es mío.

Si quieres ser perezoso, parece que sólo puede definir __hash__(self) para volver id(self):

Definido por el usuario de clases __eq__() y __hash__() los métodos por defecto;con ellos, todos los objetos comparar desigual (con la excepción de ellos mismos) y x.__hash__() devuelve id(x).

No soy un experto en python, pero ¿no tendría sentido que, cuando defina un método eq, también tenga que definir un método hash (que calcula el valor hash para un objeto) De lo contrario, el mecanismo de hash no sabría si golpeó el mismo objeto o un objeto diferente con el mismo valor de hash. En realidad, es al revés, probablemente terminaría calculando diferentes valores hash para objetos considerados iguales por su __eq__ método.

No tengo idea de cómo se llama esa función hash, ¿__hash__ quizás? :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top