为什么 Python 的 set() 在某些情况下对列表进行排序?

Why is Python's set() sorting a list in some cases?

我对这个例子中 Python 的 set() 的行为感到困惑:

random_number_list = [randint(1, 10) for _ in range(10)]
# This will be sorted!
unique_numbers = set(random_number_list)

print(
    f"random_number_list/unique_numbers with same upper bound for randint() and range():\n{random_number_list=}\n{unique_numbers=}\n"
)

random_number_list = [randint(1, 100) for _ in range(10)]
# This will not be sorted.
unique_numbers = set(random_number_list)

print(
    f"random_number_list/unique_numbers with different upper bound for randint() and range():\n{random_number_list=}\n{unique_numbers=}\n"
)

如果列表的长度和 randint() 的上限相同,则 set() 似乎正在对 random_number_list 进行排序:

➜  ch-2 python --version
Python 3.10.0
➜  ch-2 python find_k_smallest.py 
random_number_list/unique_numbers with same upper bound for randint() and range():
random_number_list=[10, 1, 2, 5, 5, 7, 8, 8, 2, 8]
unique_numbers={1, 2, 5, 7, 8, 10}

random_number_list/unique_numbers with different upper bound for randint() and range():
random_number_list=[35, 1, 17, 26, 17, 74, 26, 11, 44, 13]
unique_numbers={1, 35, 74, 11, 44, 13, 17, 26}

docs状态:

A set object is an unordered collection of distinct hashable objects.

这是怎么回事?为什么 set() 在某些情况下而不是其他情况下对 random_number_list 进行排序?

编辑 这些问题都没有解决我的问题:

实际回答你的问题。集合的许多实现使用类似于哈希表的实现。根据该哈希值对项目进行哈希处理并放入“数组”中。

请注意,对于小整数,hash(x) == x。所以 1 将进入插槽 1,2 将进入插槽 2,3 将进入插槽 3,依此类推。然后当读取元素时,您将真正对元素进行排序。

但是,如果您的整数大于数组大小,则它们在数组中的位置将以数组大小为模。它们将不再排序。

同样,我还没有真正查看 Python 实现。这只是对可能发生的事情的可能解释。

“无序”并不意味着“未排序”。这意味着没有尝试提供任何特定的命令;从实施中掉下来的顺序可能是也可能不是排序顺序。

您在评论中写道:

I'm curious as to why set() is ordering its members sometimes when the size of the list is related to the bounds of randint().

这是一个应用程序不应该关注的实现细节,即使在 Python 3.7(和 3.10)中,set 也是 documented as "unordered collection[s]". You can look up, for example, the source code of CPython to find out how sets are implemented in CPython

另请参阅:

  • Why does Python print a set of numbers as ordered