Python dict 文字和 dict(对列表)是否保持它们的键顺序?

Eri*_*got 3 python dictionary literals

在 Python 3.7+ 中,dict文字是否保持其键的顺序?例如,是否保证{1: "one", 2: "two"}在迭代时总是以这种方式(1,然后 2)对其键进行排序?(Python 邮件列表中有一个主题类似的线程,但它涉及各个方向,我找不到答案。)

同样,字典是否像dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])列表中的有序?

同样的问题也适用于其他自然排序的结构,例如 dict comprehension 和dict(sape=4139, guido=4127, jack=4098).

PS:据记载,字典保留了插入顺序。因此,该问题基本上问:是它保证数据被插入在一个字典字面的顺序列表的给予dict()

wja*_*rea 5

是的,在 Python 3.7+ 中,任何构造 dict 的方法都会保留插入顺序。


对于 dict 文字,请参阅Martijn关于如何保持键/值与声明的顺序相同的回答. 此外,从文档

如果给出了以逗号分隔的键/数据对序列,则从左到右对它们进行评估以定义字典的条目:[...]

对于理解,来自同一来源

运行推导式时,生成的键和值元素会按照它们的生成顺序插入到新字典中。

最后,dict初始化程序通过迭代其参数和关键字参数并按顺序插入每个参数来工作,类似于:

def __init__(self, mapping_or_iterable, **kwargs):
    if hasattr(mapping_or_iterable, "items"):  # It's a mapping
        for k, v in mapping_or_iterable.items():
            self[k] = v
    else:  # It's an iterable of key-value pairs
        for k, v in mapping_or_iterable:
            self[k] = v

    for k, v in kwargs.items():
        self[k] = v
Run Code Online (Sandbox Code Playgroud)

(这是基于源代码,但掩盖了许多不重要的细节,例如,这dict_init只是一个包装器dict_update_common。另外请注意,我不知道 C,但我明白了它的要点。)

这与自Python 3.6以来关键字参数以相同顺序传递字典的事实相结合,可以保留变量的顺序。dict(x=…, y=…)

  • 挑剔:它寻找“keys”方法来识别映射,而不是“items”。然后,它对尚未覆盖“__iter__”的“dict”子类使用类似“items”的迭代;对于其他一切,它会迭代键并查找值。使用“items”会更有意义,但我怀疑历史惯性使其使用“keys”。所有这些都不会使您的答案无效,因此,这只是挑剔。 (2认同)