You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python集合无序却存在固定迭代顺序的底层原理探究

Python集合“有序的无序性”底层原因及字符串哈希疑问

问题现象

已知Python集合(set)是无序的:

  • 运行第一段代码10次,约有5次输出[['DR1', 'DR12'], [], []],另5次输出[['DR12', 'DR1'], [], []]。
list_of_list = [[] for _ in range(3)]
list_of_list[0].append("DR1")
list_of_list[0].append("DR1")
list_of_list[0].append("DR1")
list_of_list[0].append("DR12")
list_of_list[0].append("DR12")
list_of_list[0].append("DR12")
list_of_list[0] = list(set(list_of_list[0]))
print(list_of_list)
  • 运行第二段代码时,for循环的5次迭代每次输出顺序都相同;重启程序后可能得到另一种顺序,但该顺序会在循环内重复5次。
for _ in range(5):
    list_of_list = [[] for _ in range(3)]
    list_of_list[0].append("DR1")
    list_of_list[0].append("DR1")
    list_of_list[0].append("DR1")
    list_of_list[0].append("DR12")
    list_of_list[0].append("DR12")
    list_of_list[0].append("DR12")
    list_of_list[0] = list(set(list_of_list[0]))
    print(list_of_list)

这一“有序的无序性”现象的底层原因是什么?同时推测:Python是否会在程序启动时为字符串的哈希计算添加随机种子?已知整数的哈希值为自身取模2**61-1,不会变化,但字符串的哈希值重启程序后会改变(如print(hash("d"))多次重启输出不同值),请确认该结论是否正确。

解答

你的推测完全正确——Python确实会在程序启动时为字符串哈希计算添加随机种子,这就是导致上述现象的核心原因,具体细节如下:

  • 集合的底层实现逻辑:集合是基于哈希表实现的,元素的存储位置由其哈希值决定,遍历集合时的顺序就是哈希表的槽位遍历顺序。因此,元素哈希值的变化会直接改变集合的输出顺序。

  • 字符串哈希的随机化机制:从Python 3.3版本开始,默认启用了字符串哈希随机化功能。程序启动时会生成一个全局随机种子,所有字符串的哈希计算都会混入这个种子。这带来两个关键特性:

    1. 同一程序运行期间,同一字符串的哈希值始终固定,因此集合的哈希表结构不会变化,遍历顺序保持一致——这就是第二段代码循环内输出顺序相同的原因。
    2. 不同程序启动实例会使用不同的随机种子,导致同一字符串的哈希值不同,集合元素的存储位置随之改变,遍历顺序也会变化——这就是第一段代码重启后输出顺序可能改变的原因。
  • 整数哈希的特殊性:整数的哈希值计算逻辑是固定的(取自身模2**61-1),不受全局随机种子的影响。因此如果集合仅包含整数,无论重启多少次程序,遍历顺序都不会发生变化(除非元素数量触发哈希表扩容,但这属于另一种场景)。

内容的提问来源于stack exchange,提问作者FluidMechanics Potential Flows

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 01:08:30