Die Python-Funktion hash(obj) berechnet einen Integer-Hash-Wert eines hashable Objekts. Hash-Werte sind das Fundament für dict- und set-Lookups in O(1). Custom-Klassen können __hash__() implementieren — und müssen dann auch __eq__() konsistent dazu definieren.
Einleitung
Die Hash-Funktion bildet ein Objekt auf eine ganze Zahl ab. Python nutzt sie als Index in Hash-Tabellen (dict, set) — daher müssen dict-Keys und set-Elemente hashable sein.
Zwei Regeln müssen Custom-Klassen einhalten:
- Konsistenz mit
__eq__:a == bmusshash(a) == hash(b)implizieren. - Stabilität über die Lebenszeit: Der Hash darf sich nicht ändern, solange das Objekt existiert.
Daher sind mutable Objekte (Listen, Dicts) standardmäßig nicht hashable — ihr Hash könnte sich nach Mutation ändern und Hash-Tabellen kaputtmachen.
Strings, Zahlen, Tupel (mit hashable Inhalt) und frozenset sind hashable. Custom-Klassen sind hashable, sobald __hash__ definiert ist (oder object-Default greift).
Syntax
hash(object)object Ein hashable Objekt.
Rückgabewert
Eine int. Bei nicht hashable Objekten: TypeError.
Beispiele
Standard-Typen
Hashes von Builtins lassen sich direkt anschauen — die konkreten Werte sind in CPython per Hash-Randomization meist pro Prozess unterschiedlich:
print(hash(42))
print(hash(3.14))
print(hash("hallo"))
print(hash((1, 2, 3)))
print(hash(None))42
322818021289917443
... (zufällig pro Prozess)
529344067295497451
0Nicht hashable
Mutable Container sind nicht hashable und werfen TypeError:
try:
hash([1, 2, 3])
except TypeError as e:
print(e)
try:
hash({"a": 1})
except TypeError as e:
print(e)unhashable type: 'list'
unhashable type: 'dict'Custom-Klasse mit hash und eq
Wer eine eigene Klasse hashable machen will, muss BEIDE Methoden konsistent implementieren:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
return isinstance(other, Point) and (self.x, self.y) == (other.x, other.y)
def __hash__(self):
return hash((self.x, self.y))
p1 = Point(1, 2)
p2 = Point(1, 2)
print(p1 == p2)
print(hash(p1) == hash(p2))
print({p1, p2}) # nur ein ElementTrue
True
{<...Point object at 0x...>}Praktische Beispiele
Hash-basierte Deduplizierung
hash() ist die Basis dafür, dass set() Duplikate erkennt — alles, was hashable ist, lässt sich so deduplizieren:
items = [(1, 2), (3, 4), (1, 2), (5, 6)]
unique = set(items)
print(unique){(1, 2), (3, 4), (5, 6)}Dataclass mit eq=True (Default) ist hashable nur mit frozen=True
Dataclasses bekommen __eq__ automatisch — __hash__ aber nur, wenn frozen=True gesetzt ist:
from dataclasses import dataclass
@dataclass(frozen=True)
class User:
name: str
age: int
u = User("Michael", 34)
print(hash(u))
print({u, User("Michael", 34)}) # Set mit nur einem Element...
{User(name='Michael', age=34)}Praktische Hinweise
- Hash ist KEIN kryptografischer Hash — er ist auf Geschwindigkeit und Verteilung optimiert, nicht auf Sicherheit. Für Security:
hashlib. - Hash-Randomization: String- und Bytes-Hashes ändern sich pro Prozess (gegen Hash-Flooding-DoS).
__hash__ = Nonesetzen in einer Klasse macht Instanzen explizit unhashable (sinnvoll für mutable Klassen mit__eq__).- Konsistenz: Wenn
__eq__implementiert ist, MUSS auch__hash__definiert sein (oder explizit aufNone) — sonst bricht das Set/Dict-Verhalten. - Verwandte Module:
hashlib(kryptografische Hashes),hmac,functools.lru_cache(nutzthashintern).