438

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.

Machavity
31.8k27 gold badges97 silver badges108 bronze badges
asked May 7, 2009 at 14:46
2
  • 3
    In CPython 3.7 (and up, presumably) you may rely on the iteration order of a dictionary matching insertion order. mail.python.org/pipermail/python-dev/2017-December/151283.html Commented Apr 19, 2018 at 18:47
  • 2
    @BallpointBen it's in CPython 3.6 and up and all other Python implementations starting with Python 3.7 Commented May 19, 2020 at 14:43

9 Answers 9

480

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.

David Fraser
7,5381 gold badge45 silver badges60 bronze badges
answered May 7, 2009 at 15:45
Sign up to request clarification or add additional context in comments.

5 Comments

apparently the statement in the 3.x documentation is clearer: "the order of items will directly correspond"
This text is missing in the 3.7 documentation. I can only assume it's because "Dict keeps insertion order" in 3.7: mail.python.org/pipermail/python-dev/2017-December/151283.html
Correct; before, the iteration order wasn't predictable, but it was consistent. Predictable iteration order implies consistency.
@chepner "consistent" meaning that if I call values() after keys(), it is guaranteed that the order of values() is the same as the order of keys()?
@robertspierre: Yes, anything else I would consider inconsistent.
107

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.

vvvvv
32.9k19 gold badges70 silver badges103 bronze badges
answered May 7, 2009 at 14:49

1 Comment

However, in case the list is altered, Pandas dataframe offers an alternative where items can be updated or deleted, and the order and the index locations of the items in a dict-like structure remain fixed.
51

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 May 7, 2009 at 15:20

Comments

22

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 Dec 16, 2017 at 19:16

Comments

7

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

k, v = zip(*d.iteritems())
answered Jun 25, 2018 at 9:06

1 Comment

In python3.x, use dict.items()
5

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 May 7, 2009 at 15:10

Comments

4

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 May 7, 2009 at 15:21

Comments

2

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 Dec 6, 2021 at 16:53

Comments

-1

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 Jul 12, 2017 at 16:10

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.