如何使一个对象正确可用?

时间:2012-06-12 09:53:47

标签: python python-3.x

这是我的代码:

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

3 个答案:

答案 0 :(得分:54)

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

在Python 2上,建议您定义__ne__以使!===保持一致。在Python 3上,默认的__ne__实现将委托给__eq__

答案 1 :(得分:15)

以下是整个代码:

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。

答案 2 :(得分:8)

The Python documentation可能会有所帮助:

  

如果某个类未定义__cmp__()__eq__()方法,则不应定义__hash__()操作;