hash()

The engine of dict and set lookups. Equal values give equal hashes; unhashable types raise.

Built-in functionPython 1.0+Live demo
Common call
hash(x)
Returns
an int — same for equal values within one process
Replaces
the internal __hash__() call that dict / set make
Watch out
string hashes are RANDOMIZED per process; `hash(-1)` is special (returns -2, never -1)
hash(objectobjectA hashable value. Numbers, strings, tuples of hashables, frozensets — hashable. Lists, dicts, sets, and anything with mutable state — NOT hashable, raises TypeError.type: Any · required)
int

Demo

Live evaluation
Try:
Inputs
xstrany value
Output
hash('5')
5

hash() returns an integer hash. For SMALL INTEGERS, hash(n) == n — except hash(-1) which returns -2 (Python reserves -1 as an error sentinel internally). For floats, hash matches int for whole-number values. For BOOLEANS, hash(True) == 1 and hash(False) == 0. For STRINGS, Python randomizes the hash per process (PEP 456, hash randomization for security) — the values shown here are illustrative and will NOT match your Python REPL exactly. The property that MATTERS: equal values always hash equally within one process.

Parameters

NameTypeRequiredDescription
objectAnyyesA hashable value. Numbers, strings, tuples of hashables, frozensets — hashable. Lists, dicts, sets, and anything with mutable state — NOT hashable, raises TypeError.

Return value

intAn integer hash for the object. Equal objects must have equal hashes. Mutable containers (list, dict, set) are unhashable and raise TypeError. For strings and bytes, the value is randomized per Python process (PEP 456) — same value within one run, different across runs.

Common patterns

Use a value as a dict key
You almost never call hash directly — you use hashable values as dict keys or set elements.
lookup = {(x, y): compute(x, y) for x, y in coords}
Test whether a value is hashable
try/except is the idiomatic check.
def is_hashable(v):
    try:
        hash(v)
        return True
    except TypeError:
        return False
Custom __hash__ on your class
Objects are hashable if they define __hash__ and __eq__ consistently.
class Point:
    def __hash__(self):
        return hash((self.x, self.y))
    def __eq__(self, other):
        return (self.x, self.y) == (other.x, other.y)

Examples

1. Small int
hash(5)
Returns
5
2. Zero
hash(0)
Returns
0
3. The -1 special
hash(-1)
Returns
-2 # -1 is reserved as error sentinel
4. Float whole
hash(3.0)
Returns
3
5. Bool matches int
hash(True), hash(False)
Returns
(1, 0)
6. Tuple of hashables
hash((1, 2, 3))
Returns
some int
7. String randomized
hash("hello")
Returns
different per process
8. List raises
hash([1, 2, 3])
Returns
TypeError: unhashable type: 'list'

Pitfalls

1. Lists, dicts, and sets are UNHASHABLE
Mutable containers cannot be dict keys or set elements. Their hash would change if you mutated them, breaking the container's invariants. Convert to tuple / frozenset / immutable form first.
List rejected
hash([1, 2])
TypeError: unhashable type: 'list'
Convert to tuple
hash((1, 2))
valid hash
2. String hashes are RANDOMIZED per process
Since Python 3.3 (PEP 456), the hash of strings and bytes is randomized at interpreter startup to defend against algorithmic complexity attacks. Two runs of `hash("hello")` give DIFFERENT results. Do not rely on cross-process consistency; use hashlib for that.
Assumed stable
hash("hello")   # cache to disk?
different each run
Use hashlib
import hashlib
hashlib.sha256(b"hello").hexdigest()
deterministic hex string
3. hash(-1) returns -2
CPython internally reserves -1 as an "error" sentinel for hash. If a value would naturally hash to -1, Python returns -2 instead. `hash(-1)` and `hash(-2)` both return -2.
Assumed identity
hash(-1)
-2
Read the docs — a small implementation detail
4. Custom __hash__ must agree with __eq__
The contract: if a == b, then hash(a) == hash(b). Defining __eq__ without __hash__ makes the class unhashable. Defining a __hash__ that violates the contract silently breaks dict / set correctness.
Missing __hash__
class C:
    def __eq__(self, o): return True
hash(C())
TypeError: unhashable type: 'C'
Define both
class C:
    def __eq__(self, o): return True
    def __hash__(self): return 0
valid, though bad hash
5. hash IS NOT a cryptographic hash
hash() is designed for dict / set lookups — fast and evenly distributed, not collision-resistant. Do not use it for security purposes. Use hashlib (sha256, blake2, ...) for cryptographic needs.
Weak for security
password_hash = hash(password)
insecure
Use hashlib
import hashlib
hashlib.sha256(pw.encode()).hexdigest()
cryptographic hash

When to use

Use it
  • Almost never directly — hashing happens implicitly in dict / set
  • Custom __hash__ on your own classes
  • Testing whether an unknown value is hashable (with try/except)
  • Occasional cache keys where the input is guaranteed hashable
Reach for something else
  • Cross-process consistency → hashlib is the right tool
  • Security or password storage → hashlib.pbkdf2 / bcrypt / argon2
  • Deterministic bucket assignment → hashlib with a fixed algorithm
  • You want the raw value → id() gives object identity instead

Notes

Complexity
O(1) for numbers; O(n) for strings, tuples, frozensets — one linear scan
Return
An integer — same for equal values within one process
CPython impl
Objects/object.c :: PyObject_Hash — calls tp_hash
Memory
No allocation
Thread-safe
Yes for immutable inputs

FAQ

Because lists are mutable. If a list were a dict key, mutating it would invalidate the dict's lookup structure. Immutable containers (tuple, frozenset) are hashable and can serve as keys.

History

1.0
hash() has been a builtin since Python 1.0.
3.3
PEP 456 — hash randomization enabled by default for strings and bytes.
3.4
PYTHONHASHSEED env var honored for reproducibility.