fork(1) download
  1. from weakref import ref, WeakKeyDictionary, WeakValueDictionary
  2.  
  3. class Id:
  4. def __init__(self, key):
  5. self._id = id(key)
  6. self.keyref = ref(key)
  7. def __hash__(self):
  8. return self._id
  9. def __eq__(self, other):
  10. return self._id == other._id and self.keyref() is other.keyref()
  11.  
  12. class WeakUnhashableKeyDictionary:
  13. def __init__(self, *args, **kwargs):
  14. # TODO Do something to initialize given args and kwargs.
  15. self.keys = WeakValueDictionary()
  16. self.values = WeakKeyDictionary()
  17.  
  18. def __getitem__(self, key):
  19. return self.values.__getitem__(Id(key))
  20.  
  21. def __setitem__(self, key, value):
  22. _id = Id(key)
  23. # NOTE This works because key holds on _id iif key exists,
  24. # and _id holds on value iif _id exists. Transitivity. QED.
  25. # Because key is only stored as a value, it does not need to be hashable.
  26. self.keys.__setitem__(_id, key)
  27. self.values.__setitem__(_id, value)
  28.  
  29. def __delitem__(self, key):
  30. self.keys.__delitem__(Id(key))
  31. self.values.__delitem__(Id(key))
  32.  
  33. class Key:
  34. __hash__ = None
  35.  
  36. d = WeakUnhashableKeyDictionary()
  37. l = [Key(), Key(), Key()]
  38. d[l[0]] = 1
  39. d[l[1]] = 2
  40.  
  41. for k in d.keys.values():
  42. l.remove(k)
  43. try:
  44. print(d[Key()])
  45. print('False match detected!')
  46. except KeyError:
  47. pass
Success #stdin #stdout 0.03s 9632KB
stdin
Standard input is empty
stdout
Standard output is empty