Python dictionary: are keys() and values() always the same order?

Question:

It looks like the lists returned by keys() and values() methods of a dictionary are always a 1-to-1 mapping (assuming the dictionary is not altered between calling the 2 methods).

For example:

>>> d = {'one':1, 'two': 2, 'three': 3}
>>> k, v = d.keys(), d.values()
>>> for i in range(len(k)):
    print d[k[i]] == v[i]

True
True
True

If you do not alter the dictionary between calling keys() and calling values(), is it wrong to assume the above for-loop will always print True? I could not find any documentation confirming this.

Asked By: Jason Coon

||

Answers:

Yes, what you observed is indeed a guaranteed property — keys(), values() and items() return lists in congruent order if the dict is not altered. iterkeys() &c also iterate in the same order as the corresponding lists.

Answered By: Alex Martelli

According to http://docs.python.org/dev/py3k/library/stdtypes.html#dictionary-view-objects , the keys(), values() and items() methods of a dict will return corresponding iterators whose orders correspond. However, I am unable to find a reference to the official documentation for python 2.x for the same thing.

So as far as I can tell, the answer is yes, but only in python 3.0+

Answered By: sykora

Yes it is guaranteed in python 2.x:

If keys, values and items views are iterated over with no intervening
modifications to the dictionary, the order of items will directly
correspond.

Answered By: Bjorn

For what it’s worth, some heavy used production code I have written is based on this assumption and I never had a problem with it. I know that doesn’t make it true though 🙂

If you don’t want to take the risk I would use iteritems() if you can.

for key, value in myDictionary.iteritems():
    print key, value
Answered By: Koen Bok

Found this:

If items(), keys(), values(),
iteritems(), iterkeys(), and
itervalues() are called with no
intervening modifications to the
dictionary, the lists will directly
correspond.

On 2.x documentation and 3.x documentation.

Answered By: nosklo

I wasn’t satisfied with these answers since I wanted to ensure the exported values had the same ordering even when using different dicts.

Here you specify the key order upfront, the returned values will always have the same order even if the dict changes, or you use a different dict.

keys = dict1.keys()
ordered_keys1 = [dict1[cur_key] for cur_key in keys]
ordered_keys2 = [dict2[cur_key] for cur_key in keys]
Answered By: jlansey

Yes. Starting with CPython 3.6, dictionaries return items in the order you inserted them.

Ignore the part that says this is an implementation detail. This behaviour is guaranteed in CPython 3.6 and is required for all other Python implementations starting with Python 3.7.

Answered By: Boris Verkhovskiy

Good references to the docs. Here’s how you can guarantee the order regardless of the documentation / implementation:

k, v = zip(*d.iteritems())
Answered By: Sassa NF

I would agree with others that in python 3.6+ it should stay the same if unaffected by user.

an example from my code few days ago:

ips = { '001' : '199.250.178.14', '002' : '199.18.2.89', '003' : '109.251.63.21' }
def run(self):
    for x, y in self.ips.items():
                try:
                    subprocess.check_call(
                    ['ping', '-n', '1', y],
                    stdout=DEVNULL,  # suppress output
                    stderr=DEVNULL
                    )
                except subprocess.CalledProcessError:
                    nextServer = ('HUB ' + x + ' is OFFLINE   ' + " IP:   " + y)

and the output is always of the same order, exactly as i inputted it i.e. only offline servers will show up in order:
HUB 003 is OFFLINE IP: 109.251.63.21
becasue first two are reachable

Hope that clears it out

Answered By: Gregory Sky
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.