70

这是我的代码:

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 个唯一的对象?

4

3 回答 3

75

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

在 Python 2 上,建议您还定义__ne__!=. ==在 Python 3 上,默认__ne__实现将为__eq__您委托。

于 2012-06-12T09:55:13.313 回答
26

这是整个代码:

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。

于 2016-07-08T04:51:38.810 回答
9

Python 文档可能会有所帮助:

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

于 2015-07-09T15:45:50.177 回答