0

How is an instance of a custom type (i.e. a user-written class) converted to a dict key in Python 3?

Consider for example the following code, where a class has a single variable that should define whether instances are alike:

class MyClass:
    def __init__(self, x):
        self.x = x


d = {MyClass(1): 1}
assert d[MyClass(1)] == 1

The assert fails because the two different MyClass instances don't resolve to the same dict key, even though they are alike.

aknuds1
  • 65,625
  • 67
  • 195
  • 317
  • And in the documentation: https://docs.python.org/3/reference/datamodel.html#object.__hash__ – jonrsharpe Oct 23 '14 at 10:53
  • @jonrsharpe That's only useful if you're looking into the \_\_hash\_\_ method, my problem was the [dict tutorial](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) only states that keys should be "immutable". I can see now however that the [dict reference itself](https://docs.python.org/3/library/stdtypes.html#mapping-types-dict) states that keys must be [hashable](https://docs.python.org/3/glossary.html#term-hashable). – aknuds1 Oct 23 '14 at 11:00
  • That documentation is referring to the built-in types (as the tutorial necessarily doesn't cover everything in full detail, and classes haven't been introduced by section 5); all built-in types implement `__eq__` and `__hash__`, the mutable types raise `TypeError` for the latter. – jonrsharpe Oct 23 '14 at 11:03
  • @jonrsharpe Yeah, I understand it refers implicitly to builtin types, but that is not what it is saying. It makes a general statement of what index keys may be, which leads to confusion (as in my case). – aknuds1 Oct 23 '14 at 11:04

1 Answers1

2

To make custom types usable as dict keys, they must define __hash__ and __eq__. I don't know if this is documented anywhere, I wasn't able to find any definition at least, but I've been told so informally:

class MyClass:
    def __init__(self, x):
        self.x = x

    def __hash__(self):
        return hash(self.x)

    def __eq__(self, rhs):
        return rhs.x == self.x


d = {MyClass(1): 1}
assert d[MyClass(1)] == 1
aknuds1
  • 65,625
  • 67
  • 195
  • 317