Aquí está mi código:¿Cómo hacer un objeto apropiadamente lavable?
class Hero:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return self.name + str(self.age)
def __hash__(self):
print(hash(str(self)))
return hash(str(self))
heroes = set()
heroes.add(Hero('Zina Portnova', 16)) # gets hash -8926039986155829407
print(len(heroes)) # gets 1
heroes.add(Hero('Lara Miheenko', 17)) # gets hash -2822451113328084695
print(len(heroes)) # gets 2
heroes.add(Hero('Zina Portnova', 16)) # gets hash -8926039986155829407
print(len(heroes)) # gets 3! WHY?
Por qué sucede esto?
El primer y el tercer objeto tienen el mismo contenido y el mismo hash pero len()
cuenta sobre 3 objetos únicos.
seguro, pero su probable que tenga '' __eq__' o __cmp__' : http://docs.python.org/glossary.html#term-hashable – nhahtdh
Dejando eso de lado, esta no es la mejor función hash (porque no has hashing una cadena general, uno de los componentes de cadena tiene una entropía mucho menor porque se sabe que consta de dígitos). Para una solución trivial pero bastante efectiva, tome los valores hash de los objetos por separado y xor ellos. Para obtener más magia, agréguelos a escala mediante una constante de número primo. –
@KonradRudolph: hay una suposición implícita en su comentario, específicamente que se necesita un "buen" hash para que el conjunto funcione bien. Este no es el caso con la implementación 'set' de Python; ver [este comentario de las fuentes de Python] (http://hg.python.org/cpython/file/26e2ee402a0b/Objects/dictobject.c#l113) para más explicaciones. –