2

I am following Exercise 40 from the book "Learn Python the Hard Way." I just noticed the following:

In [15]: stuff
Out[15]: 
{1: 'Wow',
 2: 'Neato',
 'age': 36,
 'city': 'San Francisco',
 'height': 74,
 'name': 'Zed'}

In [16]:  print stuff
{'city': 'San Francisco', 2: 'Neato', 'name': 'Zed', 1: 'Wow', 'age': 36, 'height': 74}

Why is there a difference in the order of the items of the dictionary in the two outputs?

Colorless Photon
  • 399
  • 1
  • 3
  • 19
  • 1
    If you're interested in dictionary internals, you should watch [the Mighty Dictionary](http://pyvideo.org/video/276/the-mighty-dictionary-55). – jonrsharpe Jun 23 '14 at 07:33

1 Answers1

1

The order of elements in a dictionary is unreliable, unless you use something like OrderedDict. They get shifted around for performance reasons, etc. Python makes no guarantee that the elements come out in any particular order, so you should never rely on it.

Here, there are separate code paths involved -- __repr__ vs __str__ -- so I'd guess that one of those is looking at the dictionary differently, in some way. But the short version is that, essentially, the ordering of elements in a dictionary is unreliable and you should treat it as such.

EDIT: In fact, as discussed in the comments below this answer, recent versions of Python effectively randomize the order on a run-to-run basis. The implementation relies on the output of the hash function, which, for security reasons, is seeded with a random value.

Community
  • 1
  • 1
Patrick Collins
  • 10,306
  • 5
  • 30
  • 69
  • The order is both deterministic (per implementation) and well-defined, it's just not guaranteed. – jonrsharpe Jun 23 '14 at 07:30
  • @jonrsharpe I've edited to reflect that, I wasn't aware that the implementation gave some guarantees of determinism. Tell me if you think it can be improved. – Patrick Collins Jun 23 '14 at 07:32
  • `__repr__` isn't actually what's used here. It would be used in the ordinary Python interactive interpreter, but the OP appears to be using IPython, which uses some sort of pretty-printing system (possibly `pprint.pprint`, I don't know). – user2357112 Jun 23 '14 at 07:40
  • @jonrsharpe: It's not deterministic. It's guaranteed not to change between modifications to the dict, but it is permitted to be random. With [SipHash](http://legacy.python.org/dev/peps/pep-0456/) or the old hash randomization, there actually is a random component to the dict order. – user2357112 Jun 23 '14 at 07:44
  • @user2357112 [Apparently](http://stackoverflow.com/questions/12242540/ipython-representation-of-classes) it uses `_repr_pretty_`, although I'm tempted to say that that's probably beyond the scope of the OP's question. Two different code paths are involved, which provides a good reason to get two different results from successive calls. I don't know much about dictionary internals -- in my head I treat them as being completely random -- so I'm happy to make whatever edit clarifies this best for the OP. – Patrick Collins Jun 23 '14 at 07:47
  • @user2357112 hence "per implementation" - more on that [here](http://stackoverflow.com/q/14956313/3001761). – jonrsharpe Jun 23 '14 at 07:49
  • I've tried to make edits to incorporate the info in the comments into a complete answer. I'm out of my depth, though, so if someone more knowledgeable wants to write up something complete, I'd be happy to upvote that. – Patrick Collins Jun 23 '14 at 08:34