There is a simple program:

d = dict() d["A"] = "A" d["B"] = "B" d["C"] = "C" print(d) 

We run several times and get a different conclusion:

 {'C': 'C', 'B': 'B', 'A': 'A'} {'A': 'A', 'C': 'C', 'B': 'B'} {'A': 'A', 'B': 'B', 'C': 'C'} {'C': 'C', 'A': 'A', 'B': 'B'} {'B': 'B', 'C': 'C', 'A': 'A'} 

Why it happens? It seems that the same hash function should be used and the order at each start should be the same.

Interestingly, the following code produces ten identical lines:

 for i in range(10): d = dict() d["A"] = "A" d["B"] = "B" d["C"] = "C" print(d) 

(It may depend on the platform and / or version, so I’ll immediately indicate that you used Python 3.5.1 x86 on Windows.)

1 answer 1

It seems to be used the same hash function

This is what happens in Python 2.7, but starting with Python 3.3, randomization has been introduced in the hash() function each time the interpreter is started (see security fix ).

And now, if you execute the following code:

 print('A: %d' % hash('A')) print('B: %d' % hash('B')) print('C: %d' % hash('C')) 

then Python 2.7 always gives the same answer

 A: -269909568 B: -141909181 C: -13908798 

and the dictionary is always printed in the form {'A': 'A', 'C': 'C', 'B': 'B'}

But in 3.5 the answer is always different

 A: -2050324995 B: -224727271 C: -1073853401 {'B': 'B', 'A': 'A', 'C': 'C'} A: -1049022696 B: 1500164900 C: 1196027868 {'A': 'A', 'C': 'C', 'B': 'B'} 

By the way, this is written in the docks to object.__hash__(self) :

Note: By default, the hash () values ​​of str, bytes and datetime objects are “salted” with an unpredictable random value. Although they remain constant within the individual process, they are not predictable between repeated invocations of Python.

This is intended to provide a declining-of-service caused by the careful and declining of the complexity, O (n ^ 2) complexity. See http://www.ocert.org/advisories/ocert-2011-003.html for details.

Changing hash values ​​affects the ordering of various mappings. Python has never been made to ensure this ordering (and it is typically varies between 32-bit and 64-bit builds).

See also PYTHONHASHSEED.

Changed in version 3.3: Hash randomization is enabled by default.

  • Python 2.7 may return other values. Also the -R option includes "hash randomization" and up to Python 3.3. - jfs