当我运行这行代码时,我无法理解为什么两个lists
都相同,但是从同一个列表创建的sets
不是
class Field(object):
def __init__(self, fieldnames):
self.name = fieldnames[0]
self.alias = frozenset(fieldnames)
def __eq__(self, other):
if not isinstance(other, Field):
return False
return len(self.alias & other.alias) >= 1
def __hash__(self):
return hash(self.name)
def __str__(self):
return "{field_name: %s}" % self.name
def __repr__(self):
return "<Field: (%s: %r)" %(self.name, self.alias)
In [185]: field_list1 = [["Field 1"], ["Field 2"], ["Field 3"]]
In [186]: field_list2 = [["Field 1"], ["Field 21", "Field 2"], ["Field 3"]]
In [187]: field1 = [Field(f) for f in field_list1]
In [188]: field2 = [Field(f) for f in field_list2]
In [189]: field1 == field2
Out[189]: True
In [190]: set(field1) == set(field2)
Out[190]: False
根据设置的python docs,如果第一组的每个元素都在第二组中,则两个组是相等的,反之亦然。根据这个定义,两个集合应该相等,但我不确定它们为什么不相同。
因此我想知道这种行为背后的原因?
答案 0 :(得分:3)
你在这里进行了不同的比较。
比较两个列表时,第一个列表中的每个元素都会通过GetValue
与另一个列表中的等效元素进行比较,后者会调用==
方法。虽然你的方法代码很奇怪(为什么不只是eq
?),但根据别名属性的相对大小,它会产生真或假。
然而,完全不同的工作。比较是通过哈希进行的,而不是通过相等进行的;并且您已定义了len(self.alias) == len(other.alias)
方法,以根据名称返回不同的结果,而不是别名。
答案 1 :(得分:1)
field1 == field2
使用==
oprerator(通过调用__eq__
)执行逐项比较。
set(field1) == set(field2)
检查所有元素是否都在两个集合中。集合中的元素由其哈希标识。您可以从名称中计算哈希值。列表中的某些元素具有不同的名称,因此它们是不同的集合元素。
print(field1[1].name) # 'Field 2'
print(field2[1].name) # 'Field 21'
总之,列表比较基于__eq__
,但设置比较基于__hash__
。它们基于Field
类中完全不同的计算,因此您得到的结果不同。