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