dictTools.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. """Misc dict tools."""
  2. __all__ = ["hashdict"]
  3. # https://stackoverflow.com/questions/1151658/python-hashable-dicts
  4. class hashdict(dict):
  5. """
  6. hashable dict implementation, suitable for use as a key into
  7. other dicts.
  8. >>> h1 = hashdict({"apples": 1, "bananas":2})
  9. >>> h2 = hashdict({"bananas": 3, "mangoes": 5})
  10. >>> h1+h2
  11. hashdict(apples=1, bananas=3, mangoes=5)
  12. >>> d1 = {}
  13. >>> d1[h1] = "salad"
  14. >>> d1[h1]
  15. 'salad'
  16. >>> d1[h2]
  17. Traceback (most recent call last):
  18. ...
  19. KeyError: hashdict(bananas=3, mangoes=5)
  20. based on answers from
  21. http://stackoverflow.com/questions/1151658/python-hashable-dicts
  22. """
  23. def __key(self):
  24. return tuple(sorted(self.items()))
  25. def __repr__(self):
  26. return "{0}({1})".format(
  27. self.__class__.__name__,
  28. ", ".join("{0}={1}".format(str(i[0]), repr(i[1])) for i in self.__key()),
  29. )
  30. def __hash__(self):
  31. return hash(self.__key())
  32. def __setitem__(self, key, value):
  33. raise TypeError(
  34. "{0} does not support item assignment".format(self.__class__.__name__)
  35. )
  36. def __delitem__(self, key):
  37. raise TypeError(
  38. "{0} does not support item assignment".format(self.__class__.__name__)
  39. )
  40. def clear(self):
  41. raise TypeError(
  42. "{0} does not support item assignment".format(self.__class__.__name__)
  43. )
  44. def pop(self, *args, **kwargs):
  45. raise TypeError(
  46. "{0} does not support item assignment".format(self.__class__.__name__)
  47. )
  48. def popitem(self, *args, **kwargs):
  49. raise TypeError(
  50. "{0} does not support item assignment".format(self.__class__.__name__)
  51. )
  52. def setdefault(self, *args, **kwargs):
  53. raise TypeError(
  54. "{0} does not support item assignment".format(self.__class__.__name__)
  55. )
  56. def update(self, *args, **kwargs):
  57. raise TypeError(
  58. "{0} does not support item assignment".format(self.__class__.__name__)
  59. )
  60. # update is not ok because it mutates the object
  61. # __add__ is ok because it creates a new object
  62. # while the new object is under construction, it's ok to mutate it
  63. def __add__(self, right):
  64. result = hashdict(self)
  65. dict.update(result, right)
  66. return result