问个神奇的问题

2018-07-03 19:43:06 +08:00
 firejoke
d = {str(x):y for x,y in enumerate([x for x in range(100)])}
为什么每次遍历同一个字典,
其输出顺序都是一样的,
不论是在 2.x 版本,还是 3.6 以下或是 3.6 以上
3021 次点击
所在节点    Python
15 条回复
frostming
2018-07-03 20:08:32 +08:00
不懂你什么意思,d 构造好了之后,遍历顺序当然是一定的了,都是乱的。
Python3.6 改进之处在于,它保证 d 的顺序和插入顺序一致。
20015jjw
2018-07-04 02:19:17 +08:00
lz 是不是要重新想想他是怎么读的..
firejoke
2018-07-04 08:47:55 +08:00
@frostming 是说,dict 构造好后,其遍历顺序是已经决定好了的?根据 hash 值?
firejoke
2018-07-04 08:49:28 +08:00
@20015jjw 是的......,确实以前从没想过......,我是面向问题型的: )嘻嘻~
frostming
2018-07-04 08:55:21 +08:00
@firejoke 是的
Marmot
2018-07-04 10:27:46 +08:00
<=3.5 的不是有序字典,3.6 是有序字典,3.7 我还没有看
Raymon111111
2018-07-04 10:58:00 +08:00
看看底层究竟是怎么存的就明白了
araraloren
2018-07-04 11:45:58 +08:00
xiaket
2018-07-04 12:23:12 +08:00
3.6 就已经将字典序作为特性添加到文档了, 这个特性后面应该不会再折腾了.
tkmiles
2018-07-04 14:01:03 +08:00
底层来说, dict 是用储 kv 的是一个数组, 可以称为数据数组, 数组里面的每一个元素都存储了 key/value 对象
[{key: key_object, value: value_object}, ...]

3.6 存实现的话, hash 表和数据数组是分开的(这里 hash 可以当做数组好理解, 实际实现是一个共用体, 更具体的请去看源码)
插入的时候总是 append 到数据数组, 每次遍历的时候, 都是遍历这个数据数组, 所以, 3.6+都是插入顺序
至于删除什么的, 是另外一个话题了

然后 2.x 的话, 数据数组和 hash 表是一个数组, 所以插入的时候是按 hash 值插入(当然是二次散列)
所以, 遍历的时候就是遍历 hash 表(也可以说是数据数组), 那就是按 hash 顺序返回
tkmiles
2018-07-04 14:05:22 +08:00
具体到你的例子, 因为整数的 hash 是自己的值(当然整数的 hash 不一定是自己, 这就是另外一个话题了)
所以 1 到 100 中自然不管是 hash 顺序还是插入顺序, 都是 1, 2, 3, 4, ... 这样的顺序

你可以实践一下

x={'b': 'b', 1: 1}在 3.6 和 2.x 下, 打印 keys 的区别, 注意一下, python3.6 下 ipython 打印有问题, 请使用
print(x.keys())而不是 print(x)
frostming
2018-07-04 15:17:47 +08:00
@xiaket 3.6 就已经是有序的了,但是作为字典实现的副作用隐式加入的
3.7 已经加入 release note 作为正式特性了,也就是说代码可以依靠这个特性了。
lunaticus7
2018-07-04 18:43:08 +08:00
字典遍历保序,在 py3.6 以前,只是 CPython (最常用的 python 解释器)的实现特性,并非语言特性。py3.6 后变成了语言特性。
firejoke
2018-07-05 09:05:49 +08:00
@araraloren 看楼下的回复,貌似是的
@tkmiles 基础扎实!我在 ipython 下都是直接 k,v 不加 print()

@lunaticus7 也算是 py 的进步吧
firejoke
2018-07-06 22:12:06 +08:00
@tkmiles 抱歉,我记错了,我是在 cpython 下用 k,v
不是 ipython

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/467879

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX