Python.对象集中的标识.和散列 [英] Python. Identity in sets of objects. And hashing

查看:22
本文介绍了Python.对象集中的标识.和散列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

__hash__ 和 __eq__ 如何用于集合中的识别?例如一些应该有助于解决一些多米诺骨牌难题的代码:

How do __hash__ and __eq__ use in identification in sets? For example some code that should help to solve some domino puzzle:

class foo(object):
    def __init__(self, one, two):
        self.one = one
        self.two = two
    def __eq__(self,other):
        if (self.one == other.one) and (self.two == other.two): return True
        if (self.two == other.one) and (self.one == other.two): return True
        return False
    def __hash__(self):
        return hash(self.one + self.two)

s = set()

for i in range(7):
    for j in range(7):
        s.add(foo(i,j))
len(s) // returns 28 Why?

如果我只使用 __eq__() len(s) 等于 49.它可以,因为我理解的对象(例如 1-2 和 2-1)不相同,但代表相同的多米诺骨牌.所以我添加了哈希函数.
现在它按我想要的方式工作,但我不明白一件事:1-3 和 2-2 的哈希值应该相同,所以它们应该像同一个对象一样计算,而不应该添加到集合中.但他们做到了!我卡住了.

If i use only __eq__() len(s) equals 49. Its ok because as i understand objects (1-2 and 2-1 for example) not same, but represent same domino. So I have added hash function.
Now it works the way i want, but i did not understand one thing: hash of 1-3 and 2-2 should be same so they should counted like same object and shouldn't added to set. But they do! Im stuck.

推荐答案

用于 dict/set 目的的相等性取决于 __eq__ 定义的相等性.但是,要求比较相等的对象具有相同的散列值,这就是您需要 __hash__ 的原因.请参阅这个问题了解一些类似的问题讨论.

Equality for dict/set purposes depends on equality as defined by __eq__. However, it is required that objects that compare equal have the same hash value, and that is why you need __hash__. See this question for some similar discussion.

散列本身并不能确定两个对象在字典中是否算作相同.散列就像一个捷径",只有一种方式:如果两个对象有不同的散列,它们肯定不相等;但如果它们具有相同的哈希值,它们仍然可能不相等.

The hash itself does not determine whether two objects count as the same in dictionaries. The hash is like a "shortcut" that only works one way: if two objects have different hashes, they are definitely not equal; but if they have the same hash, they still might not be equal.

在你的例子中,你定义了 __hash____eq__ 来做不同的事情.散列仅取决于多米诺骨牌上数字的总和,但相等性取决于两个单独的数字(按顺序).这是合法的,因为相同的多米诺骨牌仍然具有相同的哈希值.然而,正如我上面所说的,这并不意味着等和多米诺骨牌将被视为平等.一些不相​​等的多米诺骨牌仍然具有相等的哈希值.但是相等仍然是由__eq__决定的,而__eq__仍然按顺序查看这两个数字,所以这就是确定它们是否相等的原因.

In your example, you defined __hash__ and __eq__ to do different things. The hash depends only on the sum of the numbers on the domino, but the equality depends on both individual numbers (in order). This is legal, since it is still the case that equal dominoes have equal hashes. However, like I said above, it doesn't mean that equal-sum dominoes will be considered equal. Some unequal dominoes will still have equal hashes. But equality is still determined by __eq__, and __eq__ still looks at both numbers, in order, so that's what determines whether they are equal.

在我看来,在您的情况下,适当的做法是定义 __hash____eq__ 以依赖于 ordered 对--- 即先比较两个数中的较大者,再比较较小者.这意味着 2-1 和 1-2 将被视为相同.

It seems to me that the appropriate thing to do in your case is to define both __hash__ and __eq__ to depend on the ordered pair --- that is, first compare the greater of the two numbers, then compare the lesser. This will mean that 2-1 and 1-2 will be considered the same.

这篇关于Python.对象集中的标识.和散列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆