如何初始化Python字典以变更顺序?Python3.6以下dict无序场景疑问
Python字典顺序:初始化控制与3.6及以下版本的无序场景解析
嘿,我来帮你理清这两个关于Python字典顺序的问题——刚好在早期Python版本里踩过不少这方面的坑,分享给你:
一、怎么初始化字典并调整它的顺序?
首先得明确版本差异:Python 3.7及以后(包括CPython 3.6,但这只是当时的实现细节,官方后来才正式定为规范),字典是插入有序的;而3.6及更早的非CPython版本,字典本身是无序的。
如果是3.7+版本,想调整顺序有两种常用方法:
- 用
collections.OrderedDict:虽然普通dict已经有序,但OrderedDict自带move_to_end这类可以手动调整键位置的方法。初始化时也能直接指定非插入顺序:from collections import OrderedDict # 按自定义顺序初始化 custom_order_dict = OrderedDict([('b', 2), ('a', 1), ('c', 3)]) print(custom_order_dict) # 输出 OrderedDict([('b', 2), ('a', 1), ('c', 3)]) # 把'a'移到末尾 custom_order_dict.move_to_end('a') print(custom_order_dict) # 输出 OrderedDict([('b', 2), ('c', 3), ('a', 1)]) - 重新构造普通dict:如果只是需要改变现有字典的顺序,直接按目标键的顺序生成新字典就行:
original = {'a':1, 'b':2, 'c':3} # 按c、a、b的顺序重新生成 reordered = {k: original[k] for k in ['c', 'a', 'b']} print(reordered) # 输出 {'c': 3, 'a': 1, 'b': 2}
要是你还在使用3.6及以下的非CPython版本(比如PyPy 3.5),那普通dict本身无序,必须用OrderedDict才能控制顺序。
二、3.6及以下字典本该无序,但Shell里没重现?哪些场景会出现无序?
这里得先澄清一个误区:CPython 3.6其实已经悄悄实现了插入有序的字典,但这只是当时的实现细节,官方并没有承诺这个行为会一直保持;而Python 3.5及更早的所有版本,以及非CPython的实现(比如PyPy 3.5),字典是真·无序的。
你在Shell里没看到顺序变化,大概率是因为测试的键比较简单,刚好哈希值没冲突,或者用的是CPython 3.6。真正会出现无序的场景有这些:
- 使用Python 3.5及更早版本:比如在Python 3.5里运行下面的代码,每次输出的键顺序可能都不一样:
my_dict = {'z':26, 'a':1, 'm':13} print(my_dict) # 可能输出 {'a':1, 'z':26, 'm':13},也可能是其他乱序 - 键的哈希值冲突或字典扩容时:3.6之前的CPython字典,存储依赖键的哈希值。当多个键的哈希值冲突,或者字典元素数量达到阈值触发扩容时,遍历顺序会被打乱。比如构造一些哈希容易冲突的键:
collision_dict = {'x':1, 'y':2, 'z':3, 'aa':4, 'ab':5} print(collision_dict) # 在Python 3.5里,顺序可能和你插入的完全不一样 - 使用非CPython的Python实现:比如PyPy 3.5,它的字典实现逻辑和CPython不同,哪怕你固定插入顺序,遍历出来的顺序也可能随机变化。
- 修改字典后重新遍历:在3.6之前的版本里,当你给字典添加大量新元素触发扩容后,原来的键顺序会被打乱:
my_dict = {'a':1, 'b':2} print(list(my_dict.keys())) # 可能是 ['a','b'] # 添加多个元素触发扩容 my_dict.update({'c':3, 'd':4, 'e':5, 'f':6, 'g':7}) print(list(my_dict.keys())) # 顺序可能变成 ['b','a','d','c','f','e','g'] 这类乱序
另外要注意:如果你的代码需要兼容3.6及以下的所有版本,哪怕CPython 3.6看起来有序,也别依赖这个特性,必须用OrderedDict来保证顺序的稳定性。
内容的提问来源于stack exchange,提问作者R Yakovlev
相关产品推荐
相关产品推荐

