Set包含使用__hash__函数的用户定义类

时间:2017-02-06 05:41:30

标签: python python-2.7 hash set magic-methods

假设:

class T:
    def __hash__(self):
        return 1234

t1 = T()
t2 = T()

my_set = { t1 }

我希望以下内容能够打印True

print t2 in my_set

这不应该打印True,因为t1t2具有相同的哈希值。如何使in的{​​{1}}运算符使用给定的哈希函数?

2 个答案:

答案 0 :(得分:2)

您需要定义__eq__方法,因为只有a is b或相等a == b的实例(除了具有相同的hash)才会被set识别为相等{1}}和dict

class T:
    def __hash__(self):
        return 1234
    def __eq__(self, other):
        return True

t1 = T()
t2 = T()

my_set = { t1 }

print(t2 in my_set)  # True

data model on __hash__(和the same documentation page for Python 2)解释了这一点:

  

__hash__

     

由内置函数hash()调用,对包含setfrozensetdict. __hash__()的散列集合成员的操作应返回一个整数。 唯一需要的属性是比较相等的对象具有相同的哈希值; 建议将对象组件的哈希值混合在一起,这些哈希值也通过打包对象在比较对象时起作用进入一个元组并对元组进行哈希处理。

     

如果某个类未定义__eq__()方法,则不应定义__hash__()操作;如果它定义__eq__()但不定义__hash__(),则其实例将不能用作可散列集合中的项目。如果一个类定义了可变对象并实现了__eq__()方法,那么它不应该实现__hash__(),因为hashable集合的实现要求键的哈希值是不可变的(如果对象的哈希值发生变化,它将会在错误的哈希桶中。)

     

默认情况下,用户定义的类具有__eq__()__hash__()方法;与它们一起,所有对象都比较不相等(除了自己),x.__hash__()返回一个适当的值,x == y同时暗示x is y and hash(x) == hash(y)

(强调我的)

注意:在Python 2中,您还可以实现__cmp__方法,而不是__eq__

答案 1 :(得分:0)

在伪代码中,当x in s调用时, set .__的逻辑包含__()大致是:

h = hash(s)                          # This uses your class's __hash__()
i = h % table_size                   # This logic is internal to the hash table
if table[i] is empty: return False   # Nothing found in the set 
if table[i] is x: return True        # Identity implies equality
if hash(table[i]) != h: return False # Hash mismatch implies inequality
return table[i] == x                 # This needs __eq__() in your class