【发布时间】:2018-12-07 22:45:22
【问题描述】:
(linux 上的python 3.7.1)
我观察到一些将用户定义的对象存储在集合中的奇怪行为。这些对象非常复杂,因此不会有一个最小的例子——但我希望观察到的行为能引起比我更聪明的人的解释。这里是:
>>> from mycode import MyObject
>>> a = MyObject(*args1)
>>> b = MyObject(*args2)
>>> a == b
False
>>> z = {a, b}
>>> len(z)
2
>>> a in z
False
我的理解是,如果 (1) 它的哈希与集合中对象的哈希匹配并且 (2) 它等于该对象,则该对象是“在”集合中的。但是这些期望在这里被违反了:
>>> [hash(t) for t in z]
[1013724486348463466, -1852733432963649245]
>>> hash(a)
1013724486348463466
>>> [(hash(t) == hash(a), t == a) for t in z]
[(True, True), (False, False)]
>>> [t is a for t in z]
[True, False]
还有最奇怪的(语法上):
>>> [t in z for t in z]
[False, False]
MyObject 可能会导致它以这种方式运行?回顾一下:它有一个健全的__hash__ 和__eq__ 函数,set 只是一个股票python 集。
他们具体在这里:
class MyObject(object):
...
def __hash__(self):
return hash(self.link)
def __eq__(self, other):
"""
two entities are equal if their types, origins, and external references are the same.
internal refs do not need to be equal; reference entities do not need to be equal
:return:
"""
if other is None:
return False
try:
is_eq = (self.external_ref == other.external_ref
and self.origin == other.origin
and self.entity_type == other.entity_type)
except AttributeError:
is_eq = False
return is_eq
所有这些属性都是在这些对象上定义的。如上所示,对于集合中的一个对象,a == t 的计算结果为 True。感谢您的任何建议。
【问题讨论】:
-
我会说你得到
except AttributeError因为其中一个成员没有被定义。你可以发布你的对象的代码吗?到达AttributeError时尝试打印消息 -
self.external_ref等的比较会不会有什么可疑之处? -
我敢打赌,在将对象添加到集合后,您会变异对象。
-
另外,
__hash__和__eq__正在查看完全不相交的属性集是没有意义的。 -
但即使 hash 是伪造的,也不会阻止 set 工作。我们需要一个minimal reproducible example。你的班级太大了?将其缩小为minimal reproducible example