Python 2:“in”的不同含义集合和列表的关键字
考虑这个片段:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
意思是一样的,但是实现方式不同。列表只是检查每个对象,检查是否相等,因此它适用于您的类。设置首先对对象进行哈希处理,如果它们没有正确实现哈希,则该设置似乎不起作用。
您的类定义了
__eq__
,但未定义__hash__
,因此对于集合或字典的键无法正常工作。__eq__
和__hash__
的规则是__eq__
为 True 的两个对象也必须具有相等的哈希值。默认情况下,对象根据其内存地址进行哈希处理。因此,根据您的定义相等的两个对象不提供相同的哈希值,因此它们违反了__eq__
和__hash__
的规则。如果您提供
__hash__
实现,它将正常工作。对于您的示例代码,它可能是: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:在几乎所有哈希表实现中,包括 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__
). Thein
operator for lists just checks equality with every element of the list, which thein
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 thein
operator for sets will check in the right slot.定义与您的
__eq__()
方法相对应的__hash__()
方法。 示例。Define
__hash__()
method that corresponds to your__eq__()
method. Example.