如何正确散列一个对象?

这是我的代码:

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?

为什么会这样?
第一个和第三个对象有相同的内容和相同的散列,但是 len()告诉大约3个唯一的对象?

41435 次浏览

您还需要以与 __hash__()兼容的方式定义 __eq__()-否则,相等性将基于对象标识。

在 Python2上,建议您还定义 __ne__以使 !===保持一致。在 Python3上,默认的 __ne__实现将为您委托 __eq__

Python 文档 可能会有所帮助:

如果一个类没有定义一个 __cmp__()或者 __eq__()方法,那么它也不应该定义一个 __hash__()操作;

以下是整个代码:

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


def __eq__(self,other):
return self.name == other.name and self.age== other.age






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 2

函数识别 __eq__,因此 len 是2。