Q&A library Python

Are Python dictionaries and sets ordered?

Python Intermediate dictionariesorderingsets

Short answer

Dictionaries preserve insertion order from Python 3.7 onwards, and this is guaranteed. Sets are unordered and their iteration order must never be relied upon, even when it looks stable.

The short version

Dictionaries keep insertion order, and since Python 3.7 this is a language guarantee you can rely on. Sets are unordered: their iteration order is an implementation detail, may change between runs or versions, and must never be relied upon.

Dictionaries remember insertion order

d = {"b": 1, "a": 2}
list(d)          # ['b', 'a'] , insertion order, not sorted

Keys come back in the order they were added, not alphabetically. This is guaranteed behaviour, so you can safely rely on it for things like preserving column order or building an ordered configuration.

You no longer need collections.OrderedDict purely to preserve order. It still exists and has a couple of extra features (notably order-sensitive equality), but for ordinary use a plain dict is enough.

Sets are not ordered

s = {"b", "a", "c"}
list(s)          # some order, do not rely on it

The order you see depends on the hash values of the items and on internal details. It may look stable within one run, which is exactly what makes this dangerous: code that accidentally depends on set order can work for months and then break when the data changes or Python is upgraded.

The reproducibility trap

The most common failure is building a list from a set and expecting a consistent result.

columns = list(set(all_columns))    # order is arbitrary!

Two runs can produce different column orders, so your output file's columns move around, and a diff of two results shows spurious changes. If you need deduplication and order, use a dict.

columns = list(dict.fromkeys(all_columns))   # deduplicated, first-seen order kept

Sorting when order matters

If you want a defined order, ask for one explicitly rather than hoping.

sorted(s)                      # alphabetical, deterministic
sorted(d.items(), key=lambda kv: kv[1])   # sort a dict by value

Being explicit costs nothing and removes any dependence on internal behaviour.

String hashing is randomised

There is a further wrinkle: Python randomises string hashes between runs by default, as a security measure. That means the iteration order of a set of strings can genuinely differ from one run of your program to the next, not merely between versions.

So if a set-derived ordering ever looks stable, do not trust it. It is stable by accident, and it will bite you.

The practical rules

Use a dict when order matters and you need key-value pairs, or dict.fromkeys when you need ordered deduplication. Use a set when you need fast membership tests and genuinely do not care about order. And any time you convert a set to a list for output, sort it, so the result is deterministic and your diffs mean something.

Need this solved on your own data?

The library is free and always will be. When the problem is bigger than an answer, we take on the work.

Start a project