由于 Python 3.6 中 dict
实现的改变,它现在默认会保持顺序。那么现在 set
也能保持顺序吗?
我没有找到相关信息,但由于这两种数据结构在底层工作方式上非常相似,我认为可能是这样。
我知道并不是所有情况下都可以保证 dict
有序,但大部分情况下是有序的。正如 Python 文档中所述:
这种新实现中保留顺序的方面被认为是实现细节,不应该依赖它
由于 Python 3.6 中 dict
实现的改变,它现在默认会保持顺序。那么现在 set
也能保持顺序吗?
我没有找到相关信息,但由于这两种数据结构在底层工作方式上非常相似,我认为可能是这样。
我知道并不是所有情况下都可以保证 dict
有序,但大部分情况下是有序的。正如 Python 文档中所述:
这种新实现中保留顺序的方面被认为是实现细节,不应该依赖它
不,set
仍然是无序的。
您可以通过显示应具有“良好定义的哈希顺序”1的set
来验证这一点,以确保我们不会意外地得到一个看起来有序但实际上并非如此的set
:
>>> a_set = {3,2,1}
>>> a_set
{1, 2, 3}
>>> list(a_set)
[1, 2, 3]
如果被排序,你可以期望这些例子的结果是{3, 2, 1}
和[3, 2, 1]
。>>> a_dict = {3: 3, 2: 2, 1:1}
>>> a_dict
{3: 3, 2: 2, 1: 1}
>>> list(a_dict)
[3, 2, 1]
1“良好定义的哈希顺序”:
对于满足0 <= integer < sys.hash_info.modulus
的整数,其哈希值就是该数字本身。这意味着如果基于哈希(而不是插入时间)对集合进行排序,并且哈希值不冲突(这就是我使用小数字和仅相差一的数字的原因),那么顺序应该是确定性的,因为它们占据了集合内彼此相邻的插槽:
以下是后一种情况的示例:
>>> a_set = {6,7,8,9}
>>> a_set
{8, 9, 6, 7}
int
也会哈希到它们自己(除了 -1
),尽管我不确定确切的下限是什么。 - Chris_Rands-1
和 -2
都会哈希到 -2
,所以发生了冲突。 :) - MSeifert-1
的行为是这样的,因为它是 C 语言中的错误代码;我相信边界是(sys.maxsize // 4) - 1
,至少这是 Martijn Pieters 之前告诉我的。 - Chris_Randshash
期间捕获错误,这是有意义的。我还发现了最大值。它是sys.hash_info.modulus
。 :) - MSeifertset
在Python 3.6中没有顺序,即使作为CPython实现的细节也是如此。一个简单的示例说明了这一点:
>>> import string
>>> string.digits
'0123456789'
>>> set(string.digits)
{'7', '0', '2', '8', '6', '9', '1', '5', '4', '3'}
Python 3 文档 明确指出:
集合是一个无序的、不含重复元素的集合。