Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
641 views
in Technique[技术] by (71.8m points)

dictionary - Do Python dict literals and dict(list of pairs) keep their key order?

Do dict literals keep the order of their keys, in Python 3.7+? For example, is it guaranteed that {1: "one", 2: "two"} will always have its keys ordered this way (1, then 2) when iterating over it? (There is a thread in the Python mailing list with a similar subject, but it goes in all directions and I couldn't find an answer.)

Similarly, is a dictionary like dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) ordered like in the list?

The same question is true for other naturally ordered constructions, like dict comprehension and dict(sape=4139, guido=4127, jack=4098).

PS: it is documented that dictionaries preserve insertion order. This question thus essentially asks: is it guaranteed that data is inserted in the order of a dict literal, of the list given to dict(), etc.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes, any method of constructing a dict preserves insertion order, in Python 3.7+.


For dict literals, see Martijn's answer on How to keep keys/values in same order as declared?. Also, from the documentation:

If a comma-separated sequence of key/datum pairs is given, they are evaluated from left to right to define the entries of the dictionary: [...]

For comprehensions, from the same source.

When the comprehension is run, the resulting key and value elements are inserted in the new dictionary in the order they are produced.

Lastly, the dict initializer works by iterating over its argument and keyword arguments, and inserting each in order, similar to this:

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

(This is based on the source code, but glossing over a lot of unimportant details, e.g. that dict_init is just a wrapper on dict_update_common. Also note that I don't know C, but I got the gist of it.)

This, combined with the fact that keyword arguments pass a dictionary in the same order since Python 3.6, makes dict(x=…, y=…) preserve the order of the variables.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...