Why items order in a dictionary changed in Python? [duplicate]

I am trying to learn Python from some tutorial. Here is a simple example I encountered that puzzles me.

>>> d={"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}

>>> d
{'pwd': 'secret', 'database': 'master', 'uid': 'sa', 'server': 'mpilgrim'}

>>> d.keys()
['pwd', 'database', 'uid', 'server']

>>> d.values()
['secret', 'master', 'sa', 'mpilgrim']

As you can see in the first line where I define the dictionary, the item "pwd":"secret" is the last element in the dictionary. However, when I output the dictionary, it became the first element. And the rest part of the dictionary has been reordered.

May I know why this is happening?

If I use dict.keys() to extract the keys from a dictionary and iterate it in an order that I suppose it to be, will that cause mismatch problem?


Solution 1:

May I know why this is happening?

It is because of the way dicts are organized internally.

In short, this works via a hash-table which puts the keys into buckets according to their hash() value.

If I use dict.keys() to extract the keys from a dictionary and iterate it in an order that I suppose it to be, will that cause dismatch problem?

Depending on how you do it.

k = list(d.keys())
k.sort()
for i in k: print i, d[i]

should exactly work how you want it to work.

Solution 2:

If you want to maintain the insertion order, you can use OrderedDict. But regular dict objects store the values by hashing the key and using that for lookups, which doesn't keep the order, but makes lookup faster.

Solution 3:

All you have to worry about is, you are getting value corresponding to the key or not and that is guaranteed by dict.

d={"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
for k, v in d.items():
    print k, v

Output

pwd secret
database master
uid sa
server mpilgrim

Note: If you really want the order of the keys to be predictable, set PYTHONHASHSEED environmental variable an integer value in the range [0,4294967295]. Quoting from python --help

PYTHONHASHSEED: if this variable is set to 'random', the effect is the same as specifying the -R option: a random value is used to seed the hashes of str, bytes and datetime objects. It can also be set to an integer in the range [0,4294967295] to get hash values with a predictable seed.

Solution 4:

It is because dictionaries are not sorted.You cannot influence the key order in any way. There is Collections.OrderedDict to maintain the insertion order.

Solution 5:

Dictionaries are not sorted! Use the Key Value to get the item you want.