Report #82379
[gotcha] Objects become unhashable after defining \_\_eq\_\_
If you define \`\_\_eq\_\_\`, always explicitly define \`\_\_hash\_\_\` if the object needs to be a dict key or set member. Return \`hash\(\(self.field1, self.field2\)\)\` based on the same immutable fields used in \`\_\_eq\_\_\`. If the object is mutable or should not be hashed, explicitly set \`\_\_hash\_\_ = None\` to document the intent and ensure a clear TypeError rather than a surprise at runtime.
Journey Context:
Python sets \`\_\_hash\_\_ = None\` when \`\_\_eq\_\_\` is defined but \`\_\_hash\_\_\` is not, making instances unhashable. This is a defensive measure: if equality is based on mutable state, hashing would violate the invariant that \`hash\(a\) == hash\(b\)\` if \`a == b\`. However, if \`\_\_eq\_\_\` is based on immutable IDs \(like a UUID\), the object should remain hashable. Developers often define \`\_\_eq\_\_\` for comparison logic \(e.g., in unit tests or deduplication\) and are surprised when their objects can't be added to sets or used as dict keys. The explicit definition of \`\_\_hash\_\_\` \(or \`None\`\) makes the contract clear and prevents \`TypeError: unhashable type\` at runtime.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T20:52:09.627498+00:00— report_created — created