乍一看,x 似乎应该总是等于y,因为由相同元素构造的两个集合总是相等的:
>>> x = set([1, "a", "b", "c", "z", "f"])
>>> y = set(["a", "b", "c", "z", "f", 1])
>>> x
{1, 'z', 'a', 'b', 'c', 'f'}
>>> y
{1, 'z', 'a', 'b', 'c', 'f'}
>>> x == y
True
然而,并非总是由两个相等的集合构成的元组(或其他有序集合)相等。
实际上,您比较的结果有时是True,有时是False,至少在Python >= 3.3 中。测试以下代码:
# compare.py
x = tuple(set([1, "a", "b", "c", "z", "f"]))
y = tuple(set(["a", "b", "c", "z", "f", 1]))
print(x == y)
...一千次:
$ for x in {1..1000}
> do
> python3.3 compare.py
> done | sort | uniq -c
147 False
853 True
这是因为,从 Python 3.3 开始,字符串、字节和日期时间的哈希值是随机的,因为 security fix 的结果。根据哈希值的不同,可能会发生“冲突”,这意味着订单项存储在底层数组中(因此迭代顺序)取决于插入顺序。
以下是文档中的相关内容:
安全改进:
——https://docs.python.org/3/whatsnew/3.3.html
编辑:因为在 cmets 中提到,上面的 True/False 比率表面上令人惊讶......
集合和字典一样,是作为哈希表实现的——所以如果发生冲突,表中项目的顺序(以及迭代的顺序)将取决于首先添加的项目(在x 中有所不同)和y 在这种情况下)和用于散列的种子(自 3.3 以来的 Python 调用不同)。由于在设计上碰撞很少见,并且此问题中的示例是较小的集合,因此该问题并不像人们最初想象的那样经常出现。
有关 Python 实现字典和集合的详细说明,请参阅The Mighty Dictionary。