Skip to content

New snippet: hash(-1) #366

Open
Open
@ericbn

Description

@ericbn

Description

Small integers hash to themselves, except -1.

Snippet preview

>>> for i in range(-4, 4):
...     print(i, hash(i))
...
-4 -4
-3 -3
-2 -2
-1 -2
0 0
1 1
2 2
3 3

Explanation

See https://omairmajid.com/posts/2021-07-16-why-is-hash-in-python/ and https://www.reddit.com/r/Python/comments/oks5km/comment/h5a7ylc/

It's explained by u/ExoticMandibles on Reddit:

The reference implementation of Python is "CPython", which is almost certainly the Python you're using. CPython is written in C, and unlike Python, C doesn't have exceptions. So, in C, when you design a function, and you want your function to be able to indicate "there was an error", it has to return that error as its return value.

The hash() function in CPython can return an error, so it defines a return code of -1 to mean "there was an error". But this could be confusing if the hash worked correctly, and the actual hash of an object was -1. So the convention is: if hashing worked, and you got a -1, return -2.

There's special code in the hash function for ints ("long objects") in CPython that does exactly that:

https://github.com/python/cpython/blob/main/Objects/longobject.c#L2967

And the mentioned CPython code snippet is:

static Py_hash_t
long_hash(PyObject *obj)
{
    Py_uhash_t x;
    // ...
    if (x == (Py_uhash_t)-1)
        x = (Py_uhash_t)-2;
    return (Py_hash_t)x;
}

Checklist before calling for maintainers

  • Have you checked to ensure there aren't other open Issues for the same update/change?
  • Have you checked that this snippet is not similar to any of the existing snippets?
  • Have you added an Explanation section? It shall include the reasons for changes and why you'd like us to include them

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions