Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在字典上迭代将按排序顺序返回键_Python_Dictionary - Fatal编程技术网

Python 在字典上迭代将按排序顺序返回键

Python 在字典上迭代将按排序顺序返回键,python,dictionary,Python,Dictionary,我有一个关于python如何处理字典中的数据的问题。假设我有一个简单的字典,其中数字作为键,数字作为值,如下所示: a = { 5: 3, 20: 1, 1: 1, 5: 2, 100: 3, 11: 6, 14: 1, 15: 2, 16: 4, 17: 2, 25: 1, 19: 1 } 我想反复阅读这本字典并打印出键。每次我循环浏览字典(如下所示),它都会按递增顺序打印键 这就是我想要它做的,但我想知道,就我自己所知,为什么会发生这种情况?它是否每次都按递增顺序自动排序?正如您

我有一个关于python如何处理字典中的数据的问题。假设我有一个简单的字典,其中数字作为键,数字作为值,如下所示:

a = { 5: 3, 20: 1, 1: 1, 5: 2, 100: 3, 11: 6,
     14: 1, 15: 2, 16: 4, 17: 2, 25: 1, 19: 1 }
我想反复阅读这本字典并打印出键。每次我循环浏览字典(如下所示),它都会按递增顺序打印键

这就是我想要它做的,但我想知道,就我自己所知,为什么会发生这种情况?它是否每次都按递增顺序自动排序?正如您在上面的字典中所看到的,这些键显然不是按递增顺序排列的,但下面的输出是按递增顺序打印的

我只是想获得一个清晰的理解,任何帮助都将不胜感激。谢谢

例子 输出:

报告说:

最好将字典视为一组无序的键:值 配对,要求密钥是唯一的

与Python列表或元组不同,dict对象中的键和值对没有任何特定顺序。尽管在实例化字典时,键值对是按特定顺序存储的,但只要调用dict,就可以看到它们的存储顺序不同。
然后,如果要对它们进行排序,只需使用内置方法,字典中的整数并不总是按键排序:

a = {2:0, 9:0}
print a.keys()  # [9, 2]
Python字典是一种特殊类型的数组,其中存储值的单元格的索引是通过对键应用特殊函数(我们称之为
hash
函数)派生的。 这样,如果要检索特定键的值,可以再次计算该键的
散列
函数,该函数将返回与以前相同的结果,从而获得存储该值的索引

hash
函数将数据类型转换为整数:

print hash(1)             # 1
print hash('hello')       # 840651671246116861
print hash((2,3))         # 3713082714463740756
每种类型都可以定义自己的散列计算方法,
int
通常返回自身:

print hash(1)             # 1
print hash(20)            # 20
print hash(1000)          # 1000
正如您所看到的,数字很快就会变大,我们不希望一个包含84065167124611661个单元格的数组只是为了保存字符串
hello
。 为了避免这个问题,我们可以创建一个包含
n
元素的数组,然后使用散列的剩余部分除以
n
作为索引

例如,如果我们想在8个元素的数组中查找
hello
的索引:

print hash('hello') % 8   # 5
因此,我们的字典将知道键
hello
的值位于索引8。字典就是这样实现的

那么,为什么键上的
{2:0,9:0}
不是按顺序排列的呢?这是因为python字典是用8个元素创建的,并且会根据需要增长(更多介绍)

让我们计算索引,以将具有
key=2
key=9
的数据存储在具有
n=8
的字典中:

print hash(2) % 8         # 2  [hash(2) = 2 and 2 % 8 = 2]
print hash(9) % 8         # 1  [hash(9) = 9 and 9 % 8 = 1]
这意味着包含字典数据的数组将是:

| index | key | value |
|-------|-----|-------|
|   0   |     |       |
|   1   |  9  |   0   |
|   2   |  2  |   0   |
|   3   |     |       |
|   4   |     |       |
|   5   |     |       |
|   6   |     |       |
|   7   |     |       |
当对其进行迭代时,顺序将在此表示中显示,因此
9
将位于
2
之前

你可以阅读更多关于这个主题的文章

每次我循环浏览字典(如下图所示),它都会打印出来 按键按递增顺序排列

这只是偶然的。字典是无序的对象集合,可以通过键访问

没有“自动排序”或任何其他类型的排序

只需想一秒钟——设置自己的关键点就是能够通过它们获取,因此关键点有一个“顺序”并不重要——关键点是你知道如何引用每个对象,因为你设置了它的关键点。这使得获取对象的速度非常快;因为它很容易找到。没有重复的键,因此字典内部可以以优化的方式存储,以便快速访问

将其与已排序的列表进行比较(其顺序是有保证的)。在列表中,关键是通过对象在列表中的引用来获取对象,也就是说,通过对象相对于列表中其他对象的位置来获取对象。因此,维持秩序是有意义的

元组与列表相似,因为元组是有序的。元组和列表之间的区别之一是元组一旦设置就不能更改(不能“增长”或“收缩”元组)。为了修改一个元组,必须创建另一个元组。所以要“增长”一个元组,将两个元组相加,得到第三个不同的元组。原来的两个元组保持不变


如果你想知道字典实现背后的技术细节,以及它们是如何工作的,“在引擎盖下”有一个很好的答案,里面有各种各样的信息。

如果你想知道Python为什么总是按顺序排列键……答案是它没有

如果您想知道为什么某些特定版本的特定Python实现会将特定键按顺序排列,那么唯一真正的答案就是源代码

对于CPython(您可能正在使用的实现,如果您不知道正在使用哪个实现),源代码位于
Objects/dictobject.c
。它在3.4中发生了戏剧性的变化,在此之前,我认为是2.6/3.2,历史上还有一些其他不太戏剧性的变化。因此,您必须确保查找您真正关心的版本。对于3.4,来源为。它是C语言的,但是有一些很好的注释解释了它的功能。如果您真的想探索它,您甚至可以将它移植到Python并在
pdb
下运行它

除非您理解哈希表,否则从阅读代码中可能不明显的一个关键问题是这里有两个“巧合”,而不仅仅是一个。首先,某些版本的CPython在一次构造完一个小dict后,会根据它们的散列值对键进行排序。其次,到目前为止,在CPython的所有版本中,小整数都会散列到它们自己,这与几乎任何其他类型不同——“按散列值排序”也意味着“按值排序”。

这就是
print hash(2) % 8         # 2  [hash(2) = 2 and 2 % 8 = 2]
print hash(9) % 8         # 1  [hash(9) = 9 and 9 % 8 = 1]
| index | key | value |
|-------|-----|-------|
|   0   |     |       |
|   1   |  9  |   0   |
|   2   |  2  |   0   |
|   3   |     |       |
|   4   |     |       |
|   5   |     |       |
|   6   |     |       |
|   7   |     |       |