Containers that take hashable objects (such as dict
keys or set
items). As such, a dictionary can only have one key with the value 1
, 1.0
or True
etc. (note: simplified somewhat - hash collisions are permitted, but these values are considered equal)
My question is: is the parsing order well-defined and is the resulting object predictable across implementations? For example, OSX Python 2.7.11 and 3.5.1 interprets dict
like so:
>>> { True: 'a', 1: 'b', 1.0: 'c', (1+0j): 'd' }
{True: 'd'}
In this case, it appears that the first key and the last value are preserved.
Similar, in the case of set
:
>>> { True, 1, 1.0, (1+0j) }
set([(1+0j)])
Here it appears that the last item is preserved.
But (as mentioned in comments):
>>> set([True, 1, 1.0])
set([True])
Now the first in the iterable is preserved.
The documentation notes that the order of items (for example in dict.items
) is undefined, however my question refers to the result of constructing dict
or set
objects.
dictionary-displays
set displays
There is a difference in calling the set constructor or using a comprehension and the plain literal.
Output:
How they are created influences the outcome:
Python only runs the
BUILD_SET
bytecode when you pass a pure literal separated by commas as per:When a comma-separated list of expressions is supplied, its elements are evaluated from left to right and added to the set object.
The line for the comprehension:
When a comprehension is supplied, the set is constructed from the elements resulting from the comprehension.
So thanks to Hamish filing a bug report it does indeed come down to the
BUILD_SET
opcode as per Raymond Hettinger's comment in the link The culprit is the BUILD_SET opcode in Python/ceval.c which unnecessarily loops backwards, the implementation of which is below: