Python - hash and `None` question

Why is the None hash equal to -1042159082 (which, it seemed to me, equal to the number of bytes in Gigabyte, is denied)?

I understand that this does not affect my code, but I'm curious.

Hashes are used to search for dictionary keys, so I decided to experiment:

 >>> D = {-1042159082: 'Hello', None: 'Hi'} >>> D[None] 'Hi' >>> D[-1042159082] 'Hello' >>> 

I understand this as Python, seeing two identical hashes, and then checking the type to find out what. Is it correct?

 >>> {False: 'Hello', 0: 'Hi'} {False: 'Hi'} >>> {0: 'Hi', False: 'Hello'} {0: 'Hello'} 

This is just weird. Moreover, the first key is stored and the second value is stored.

Is this magic, or can someone help me understand?

+4
source share
4 answers

About 2 values ​​that can produce the same result when passed to the hash() built-in function ( None and -1042159082 in the -1042159082 question):

This is called collision (see this page on Wikipedia for more information on collisions).

The hashing algorithm that Python uses has a special way of figuring out what value a person really wants when there is a collision (see this page in the CPython source code (the main Python interpreter), starting at line 51, for collision information for dicts, in While writing this answer, this also contains notes on how dicts are executed).

For what happens with 0 and False (and more useful information), see other answers to the current question.

+6
source

You cannot and should not depend on the specific hash value for a Python object. It is implemented and machine dependent. On my car:

 >>> hash(None) 268532216 

Regarding populating dict objects (there is no hash object in Python), perhaps the following:

 >>> False == 0 True >>> {0: 'Hello', 0: 'Hi'} {0: 'Hi'} >>> {0: 'Hi', 0: 'Hello'} {0: 'Hello'} >>> {False: 'Hello', False: 'Hi'} {False: 'Hi'} >>> {False: 'Hi', False: 'Hello'} {False: 'Hello'} 

When using the dict constructor, you supply two key=value pairs, but they both have the same key (i.e., a hash value), therefore, since the key values ​​in the dict must be unique, the last value is the value that is stored. In other words, each of the above constructors creates one dict element:

 >>> print {False: 'Hello', 0: 'Hi'} {False: 'Hi'} 

See here for more details.

+3
source

No, even if two objects have the same hash, they still will not cause key collisions. Python detects this and works around it (although please don't ask me how).

But False matches 0 , and True matches 1 , so when you use both in a dict construct, you update the value when you add another element using the same key.

+2
source

How do you see No hashes for this value?

 >>> d = {None:'hi'} >>> d.get(-1042159082) >>> d.get(None) 'hi' >>> >>> hash(None) 268532214 >>> 

I would never rely on the value of None hashing.

Regarding dictionary resolution using a literal, I assume that internally, defining a key that is β€œequal” to another will simply do the update instead of directly adding it.

 >>> class Key(object): ... key = '1' ... def __hash__(self): ... return 1 ... def __eq__(self, other): ... return hash(self) == hash(other) ... >>> class FakeKey(Key): ... key = '2' ... >>> k = Key() >>> >>> fk = FakeKey() >>> d = {k:k,fk:fk} >>> d {<__main__.Key object at 0x100489f10>: <__main__.FakeKey object at 0x100489fd0>} >>> ref = d[k] >>> ref.key '2' >>> d.keys()[0].key '1' >>> 

It appears that I am right (only appears).

0
source

Source: https://habr.com/ru/post/1345394/


All Articles