The catch is that the unhashable objects aren't actually stored in the mapping. Only their IDs are. Thus you must also store the actual objects somewhere else.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
try: from collections.abc import MutableMapping except ImportError: from collections import MutableMapping class IDKeyedMapping(MutableMapping, dict): '''A dict that can take mutable objects as keys.''' def __len__(self): return dict.__len__(self) def __iter__(self): return dict.__iter__(self) def __contains__(self, key): return dict.__contains__(self, id(key)) def __getitem__(self, key): return dict.__getitem__(self, id(key)) def __setitem__(self, key, value): dict.__setitem__(self, id(key), value) def __delitem__(self, key): dict.__delitem__(self, id(key)) def values(self): return dict.values(self) def items(self): return dict.items(self)
Alterately, implement __hash__() on your mutable object's class:
class MyType: # Python 3 implicit base: object def __hash__(self): return id(self)
If you want to use a type you don't control, subclass it:
class NewType(original_type): def __hash__(self): return id(self)
If that doesn't work (as is the case with a very few built-in types) or you have an existing object, you could write a simple wrapper class that also implements __hash__().