python里字典是无序的

探讨Python字典在不同版本中的实现细节,特别是在CPython3.6中字典是否保持插入顺序的问题。虽然规范不保证字典有序,但实际实现可能因版本而异。
部署运行你感兴趣的模型镜像

详情请参考:https://www.zhihu.com/question/65855807

 

 

关于 Python 字典的 values() 方法返回值的顺序?

dict_mark = {'Wang': 'C', 'Li': 'B', 'Ma': 'A'}
s = ''
for c in dict_mark.values():
    s += c
print(s)

关于这个字典打印出来一直是 CBA 的顺序,可是字典不是应该无序吗?stackoverflow的前辈们的答案我看的一知半解,能否请教知友们呢?

问题地址

另一答案地址

还有一个关于 dictionary 的(字典变有序了?)

关注者

38

被浏览

8,727

关注问题写回答

​添加评论

​分享

​邀请回答

收起

12 个回答

默认排序​

廖雪峰

廖雪峰

业余马拉松选手 http://www.liaoxuefeng.com

43 人赞同了该回答

规范是指dict遍历是不保证顺序的,但一定保证每个元素都被遍历一次

实现可以是无序,也可以是有序,都符合规范

Py3.5是无序的,3.6是有序的,但不能说dict就是有序的,因为如果3.7改成无序的也是正确的实现。

如果要使用有序dict,必须用OrderedDict

发布于 2017-09-26

​赞同 43​​10 条评论

​分享

​收藏​感谢

Coldwings

Coldwings

 

Python 话题的优秀回答者

9 人赞同了该回答

如果按照语言规范来看,Python的规范里没有说明Dict是一个有序的类型。换句话说,dict就是无序的,因为语言规范不保证它按照什么顺序出来。要有序,请使用OrderedDict。

但是无序不是说每次输出结果都不同,无序只是指结果不保证一定与插入顺序一致而已。

CPython 3.6里对dict有个新的实现,使得字典内部存储的顺序不仅仅与key有关,还与插入顺序有关。但是有关并不代表它就一定按照插入顺序依次出现(似乎当字典实现在内存中进行扩展的时候就可能造成结果不一致),只不过表示如果key相同,插入顺序相同,那么结果也是相同的。

在此之前,用values和keys方法取到的list仅与key(准确的说是key的__hash__)有关而与插入顺序无关。

编辑于 2017-09-25

​赞同 9​​4 条评论

​分享

​收藏​感谢

灵剑

灵剑

微博一般不上 http://weibo.com/hubo1016

21 人赞同了该回答

无序的不代表随机的,也不代表每次都是随机的,这些词有细微的差异。无序的只是说,你不该对顺序有任何假定,既不能假定有确定顺序,也不能假定没有确定顺序。

发布于 2017-11-17

​赞同 21​​6 条评论

​分享

​收藏​感谢

Pegasus Wang

Pegasus Wang

知乎 Python 后端工程师,Pythonista and Vimer

1 人赞同了该回答

Python dictionary implementation

 

你看下 dict 的 CPython hash 实现就了解了

发布于 2017-11-17

​赞同 1​​添加评论

​分享

​收藏​感谢

Revive

Revive

码农 / 死宅 / 玩家

1 人赞同了该回答

一般语言里的dict结构只是表面上说自己是无序的,实际上根据内部实现会有自己的一套顺序,只是这个顺序可能比较古怪,比较混沌,比较没有统一标准,甚至可能以后实现变了顺序也会变,所以设计者也不想告诉你究竟是个什么顺序,但是每次读出来都会根据这个顺序出。
不过也有比较奇葩的语言每次读出来的顺序都不一样,比如说golang。

编辑于 2017-09-26

​赞同 1​​添加评论

​分享

​收藏​感谢

李强

李强

1 人赞同了该回答

Python内部对key的索引是有序的,具体我举个例子.

In [6]: hash("acc")&7

Out[6]: 2

In [7]: hash("abc")&7

Out[7]: 4

In [8]: {"acc":"acc","abc":"abc"}

Out[8]: {'abc': 'abc', 'acc': 'acc'}

输入字典顺序是先key"acc"后key"abc",输出位置就倒了.

当然除了整数hash("key")&7的值好像每次重新开一个Python解释器都会变.所以说可能你的hash("abc")&7这个值也会和我的不一样.

 

回到你的问题.

In [9]: hash('Wang')&7

Out[9]: 1

 

In [10]: hash('Li')&7

Out[10]: 1

 

In [11]: hash('Ma')&7

Out[11]: 5

 

In [12]: {'Wang': 'C', 'Li': 'B', 'Ma': 'A'}

Out[12]: {'Li': 'B', 'Ma': 'A', 'Wang': 'C'}

我现在的字典顺序就变了呢.

 

但是实际上这个返回顺序并不重要.

编辑于 2017-11-17

​赞同 1​​添加评论

​分享

​收藏​感谢收起​

绫波limbo

绫波limbo

我爱python一辈子

2 人赞同了该回答

没有顺序,包括.keys取键,.values取值,字典无序存储不是逗你玩的,不管你在命令行里输出多少次一样的顺序都不要上当!!!
如果要取字典顺序,请你老老实实用ordereddict!!
这是我有一次在spark做需求的血泪教训

发布于 2017-09-26

​赞同 2​​2 条评论

​分享

​收藏​感谢

梧桐

梧桐

答非所问的 见一个举报一个 呵呵 继续抖机灵给我看

字典是有顺序的 但是顺序是不定的 不信你可以迭代试试

发布于 2017-11-24

​赞同​​添加评论

​分享

​收藏​感谢

Tux ZZ

Tux ZZ

Nothing-to-research Researcher

补充 

@灵剑

 的回答。
cpython3.6的dict实现搬了pypy的实现,是保持顺序的。
** 但你依然不能把dict当作有序的来使用 **
因为dict的标准规定*不保证*有顺序,要保证有顺序的请用OrderedDict

编辑于 2017-11-22

​赞同​​添加评论

​分享

​收藏​感谢

ShengCiun Liang

ShengCiun Liang

反对任何形式的平权

理论上肯定有序的 你既然有放入的顺序 查看肯定就有顺序 只是不可以顺序的方式看待

发布于 2017-11-20

​赞同​​添加评论

​分享

​收藏​感谢

陈子坤

陈子坤

结构工程师,Python,Go, 大数据, WEB后端

字典是无序的,这句话是对的。但是字典的存储过程却是按顺序的。

 

字典的存储背后的逻辑是散列表,也就是稀疏数组。dict初始化之后,Python解释器会给dict分配一定的空间,往字典里添加是按顺序添加的。

 

但是,如果如果继续往字典里添加新键,有可能会引起Python解释器对存储空间的扩容,扩容的过程会新建散列表,然后复制已有的元素到新散列表,这个过程可能会引起散列冲突,导致dict的键值对的次序发生变化。

 

《流畅的Python》一书有关于字典的存储更为详细的介绍。

如果不了解散列表,可以查资料。

编辑于 2017-11-18

​赞同​​添加评论

​分享

​收藏​感谢匿名用户

匿名用户

values 和 keys 保持遍历时键对对应顺序一致。

您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think>好的,用户想了解Python字典的顺序特性以及版本差异。首先,我需要回忆一下Python不同版本中字典的实现变化。记得在Python 3.6之前,字典无序的,插入顺序不会被保留。但Python 3.7之后,字典变成有序的了,这个变化可能需要详细说明。 然后,我需要确认用户提到的参考资料。引用[1]提到Python 3.6开始字典变得有序,而引用[3]和[4]也提到相关的内容。要确保回答正确引用这些资料,特别是版本差异的部分。 接下来,用户的问题包括字典是否有序和版本差异,需要分点回答。首先明确说明Python 3.7+的字典是有序的,而在3.6是作为实现细节,之前版本是无序的。然后对比不同版本的区别,可能还要提到如何在不同版本中保持有序,比如使用OrderedDict。 还要注意用户可能关心的实际应用,比如在需要有序字典时应该如何选择数据结构。可能需要提到OrderedDict在旧版本中的使用,以及现在版本中普通字典已经有序的情况下的最佳实践。 另外,用户可能会对如何判断当前环境字典是否有序感兴趣,可能需要指导他们如何检查Python版本或者测试字典的顺序。 需要确保回答结构清晰,分版本说明,并给出实际建议。同时,引用正确的参考资料,比如引用[1]和[3]关于版本变化和排序方法的部分。 最后,生成的相关问题需要围绕字典的有序性展开,比如如何保持顺序,如何排序字典,以及版本升级的影响等。这样可以帮助用户进一步探索相关主题。 总结回答的结构: 1. 明确回答字典Python 3.7+是有序的,之前版本无序。 2. 分版本详细说明差异,包括3.6的实现细节。 3. 提供实际开发建议,如使用OrderedDict的情况。 4. 引用相关资料支持每个观点。 5. 生成相关问题引导深入学习。</think>### Python字典顺序特性及版本差异解析 #### 1. Python字典的有序性结论 Python 3.7+版本中**标准字典默认保持插入顺序**,这是官方语言规范特性[^1]。Python 3.6中该特性是CPython实现的细节,而Python 3.7之前版本字典无序的[^1][^3]。 #### 2. 版本差异对比表 | 版本范围 | 顺序特性 | 类型安全性 | |---------------|----------------------------------|-----------------------| | Python <3.6 | 完全无序 | 无法保证插入顺序 | | Python 3.6 | 实现层面有序(CPython特性) | 非官方规范,跨解释器不兼容 | | Python ≥3.7 | 语言规范定义的有序 | 官方保证 | #### 3. 具体表现验证 ```python # Python 3.8+测试示例 test_dict = {} test_dict['a'] = 1 test_dict['b'] = 2 print(list(test_dict)) # 输出顺序始终为['a', 'b'] ``` #### 4. 旧版本兼容方案 对于需要支持多版本的环境,推荐使用$collections.OrderedDict$: ```python from collections import OrderedDict od = OrderedDict([('a', 1), ('b', 2)]) ``` #### 5. 内存结构优化 Python 3.6采用紧凑型字典存储结构,通过两个数组实现: - 索引表:存储条目索引 - 条目表:存储(key, value)对 这种设计使字典内存使用量减少20-25%[^4] #### 6. 实际开发建议 - 依赖字典顺序时需明确标注最低版本要求 - 跨版本项目建议添加顺序性验证: ```python import sys if sys.version_info < (3,7): print("需要OrderedDict保证顺序") ``` - 排序操作建议使用$sorted()$函数: $$sorted_dict = dict(sorted(original_dict.items(), key=lambda x: x[1]))$$ [^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值