python set.__contains__ 的意外行为
借用 __contains__
文档中的文档
print set.__contains__.__doc__
x.__contains__(y) <==> y in x.
这对于原始对象(如 int、basestring 等)似乎工作得很好。但对于定义 __ne__
和 的用户定义对象>__eq__
方法,我得到了意想不到的行为。这是示例代码:
class CA(object):
def __init__(self,name):
self.name = name
def __eq__(self,other):
if self.name == other.name:
return True
return False
def __ne__(self,other):
return not self.__eq__(other)
obj1 = CA('hello')
obj2 = CA('hello')
theList = [obj1,]
theSet = set(theList)
# Test 1: list
print (obj2 in theList) # return True
# Test 2: set weird
print (obj2 in theSet) # return False unexpected
# Test 3: iterating over the set
found = False
for x in theSet:
if x == obj2:
found = True
print found # return True
# Test 4: Typcasting the set to a list
print (obj2 in list(theSet)) # return True
那么这是一个错误还是一个功能?
Borrowing the documentation from the __contains__
documentation
print set.__contains__.__doc__
x.__contains__(y) <==> y in x.
This seems to work fine for primitive objects such as int, basestring, etc. But for user-defined objects that define the __ne__
and __eq__
methods, I get unexpected behavior. Here is a sample code:
class CA(object):
def __init__(self,name):
self.name = name
def __eq__(self,other):
if self.name == other.name:
return True
return False
def __ne__(self,other):
return not self.__eq__(other)
obj1 = CA('hello')
obj2 = CA('hello')
theList = [obj1,]
theSet = set(theList)
# Test 1: list
print (obj2 in theList) # return True
# Test 2: set weird
print (obj2 in theSet) # return False unexpected
# Test 3: iterating over the set
found = False
for x in theSet:
if x == obj2:
found = True
print found # return True
# Test 4: Typcasting the set to a list
print (obj2 in list(theSet)) # return True
So is this a bug or a feature?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
对于
set
和dicts
,您需要定义__hash__
。任何两个相等的对象都应该具有相同的哈希值,以便在set
和dicts
中获得一致/预期的行为。我建议使用
_key
方法,然后在需要比较项目部分的任何地方引用该方法,就像您从__ne____eq__
一样code> 而不是重新实现它:For
set
s anddicts
, you need to define__hash__
. Any two objects that are equal should hash the same in order to get consistent / expected behavior inset
s anddicts
.I would reccomend using a
_key
method, and then just referencing that anywhere you need the part of the item to compare, just as you call__eq__
from__ne__
instead of reimplementing it:这是因为
CA
没有实现__hash__ :
一个合理的实现是
This is because
CA
doesn't implement__hash__
A sensible implementation would be:
集合
散列它的元素以允许快速查找。您必须覆盖 __hash__ 方法,以便可以找到元素:列表不使用散列,而是像
for
循环一样比较每个元素。A
set
hashes it's elements to allow a fast lookup. You have to overwrite the__hash__
method so that a element can be found:Lists don't use hashing, but compare each element like your
for
loop does.