简体   繁体   English

Python 中的 set() 使用什么来测试对象之间的相等性?

[英]What does set() in Python use to test equality between objects?

I have written some code in Python which has a class called product and overrided the magic functions __eq__ and __hash__ .我用 Python 编写了一些代码,其中有一个名为 product 的类并覆盖了魔术函数__eq____hash__ Now I need to make a set which should remove duplicates from the list based on the ID of the product.现在我需要创建一个集合,它应该根据产品的ID从列表中删除重复项。 As you can see the output of this code the hashes of two objects are the same, yet when i make a set of those two objects the length is 2 not one.正如您所看到的这段代码的输出,两个对象的哈希值是相同的,但是当我创建一组这两个对象时,长度是 2 而不是 1。

But, when i change the __eq__ method of the code to this但是,当我将代码的__eq__方法更改为此

def __eq__(self, b) -> bool:
    if self.id == b.id:
        return True
    return False

and use it with the same hash function it works and the length of the set is 1. So i am confused whether the set data-structure uses the __eq__ method to test for equality or the __hash__ method.并将它与它工作的相同散列函数一起使用,并且集合的长度为 1。所以我很困惑集合数据结构是使用__eq__方法来测试相等性还是使用__hash__方法。

Equality tests can be expensive, so the set starts by comparing hashes.相等测试可能很昂贵,因此该集合从比较散列开始。 If the hashes are not equal, then the check ends.如果散列不相等,则检查结束。 If the hashes are equal, the set then tests for equality.如果散列相等,则集合测试相等。 If it only used __eq__ , it might have to do a lot of unnecessary work, but if it only used __hash__ , there would be no way to resolve a hash collision.如果它只使用__eq__ ,它可能需要做很多不必要的工作,但如果它只使用__hash__ ,将无法解决哈希冲突。

Here's a simple example of using equality to resolve a hash collision.这是一个使用相等来解决哈希冲突的简单示例。 All integers are their own hashes, except for -1 :所有整数都是它们自己的哈希值,除了-1

>>> hash(-1)
-2
>>> hash(-2)
-2
>>> s = set()
>>> s.add(-1)
>>> -2 in s
False

Here's an example of the set skipping an equality check because the hashes aren't equal.这是由于散列不相等而跳过相等检查的集合的示例。 Let's subclass an int so it return a new hash every second:让我们继承一个int类,让它每秒返回一个新的散列:

>>> class TimedInt(int):
...  def __hash__(self):
...   return int(time.time())
...
>>> a = TimedInt(5)
>>> a == 5
True
>>> a == a
True
>>> s = set()
>>> s.add(a)  # Now wait a few seconds...
>>> a in s
False

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM