Python 2:“in”的不同含义集合和列表的关键字

发布于 2025-01-04 13:27:32 字数 590 浏览 1 评论 0原文

考虑这个片段:

class SomeClass(object):

    def __init__(self, someattribute="somevalue"):
        self.someattribute = someattribute

    def __eq__(self, other):
        return self.someattribute == other.someattribute

    def __ne__(self, other):
        return not self.__eq__(other)

list_of_objects = [SomeClass()]
print(SomeClass() in list_of_objects)

set_of_objects = set([SomeClass()])
print(SomeClass() in set_of_objects)

它的计算结果是:

True
False

任何人都可以解释为什么“in”关键字对于集合和列表有不同的含义吗? 我希望两者都返回 True,特别是当被测试的类型定义了相等方法时。

Consider this snippet:

class SomeClass(object):

    def __init__(self, someattribute="somevalue"):
        self.someattribute = someattribute

    def __eq__(self, other):
        return self.someattribute == other.someattribute

    def __ne__(self, other):
        return not self.__eq__(other)

list_of_objects = [SomeClass()]
print(SomeClass() in list_of_objects)

set_of_objects = set([SomeClass()])
print(SomeClass() in set_of_objects)

which evaluates to:

True
False

Can anyone explain why the 'in' keyword has a different meaning for sets and lists?
I would have expected both to return True, especially when the type being tested has equality methods defined.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

假扮的天使 2025-01-11 13:27:33

意思是一样的,但是实现方式不同。列表只是检查每个对象,检查是否相等,因此它适用于您的类。设置首先对对象进行哈希处理,如果它们没有正确实现哈希,则该设置似乎不起作用。

您的类定义了 __eq__,但未定义 __hash__,因此对于集合或字典的键无法正常工作。 __eq____hash__ 的规则是 __eq__ 为 True 的两个对象也必须具有相等的哈希值。默认情况下,对象根据其内存地址进行哈希处理。因此,根据您的定义相等的两个对象不提供相同的哈希值,因此它们违反了 __eq____hash__ 的规则。

如果您提供 __hash__ 实现,它将正常工作。对于您的示例代码,它可能是:

def __hash__(self):
    return hash(self.someattribute)

The meaning is the same, but the implementation is different. Lists simply examine each object, checking for equality, so it works for your class. Sets first hash the objects, and if they don't implement hash properly, the set appears not to work.

Your class defines __eq__, but doesn't define __hash__, and so won't work properly for sets or as keys of dictionaries. The rule for __eq__ and __hash__ is that two objects that __eq__ as True must also have equal hashes. By default, objects hash based on their memory address. So your two objects that are equal by your definition don't provide the same hash, so they break the rule about __eq__ and __hash__.

If you provide a __hash__ implementation, it will work fine. For your sample code, it could be:

def __hash__(self):
    return hash(self.someattribute)
三生一梦 2025-01-11 13:27:33

在几乎所有哈希表实现中,包括 Python 的哈希表实现,如果您重写相等方法,则必须重写哈希方法(在 Python 中,这是 __hash__)。列表的 in 运算符仅检查列表中每个元素的相等性,其中集合的 in 运算符首先对您要查找的对象进行哈希处理,然后检查该列表中的对象哈希表的槽,然后检查槽中是否有任何内容是否相等。因此,如果您覆盖 __eq__ 而不覆盖 __hash__,则无法保证集合的 in 运算符会签入正确的槽。

In pretty much any hashtable implementation, including Python's, if you override the equality method you must override the hashing method (in Python, this is __hash__). The in operator for lists just checks equality with every element of the list, which the in operator for sets first hashes the object you are looking for, checks for an object in that slot of the hashtable, and then checks for equality if there is anything in the slot. So, if you override __eq__ without overriding __hash__, you cannot be guaranteed that the in operator for sets will check in the right slot.

御弟哥哥 2025-01-11 13:27:33

定义与您的 __eq__() 方法相对应的 __hash__() 方法。 示例

Define __hash__() method that corresponds to your __eq__() method. Example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文