Chained map lookups « Python recipes « ActiveState Code (original) (raw)

Encapsulates lookups into a series of namespaces.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import UserDict class Chainmap(UserDict.DictMixin): """Combine multiple mappings for sequential lookup. For example, to emulate Python's normal lookup sequence: import __builtin__ pylookup = Chainmap(locals(), globals(), vars(__builtin__)) """ def __init__(self, *maps): self._maps = maps def __getitem__(self, key): for mapping in self._maps: try: return mapping[key] except KeyError: pass raise KeyError(key) if __name__ == "__main__": d1 = {'a':1, 'b':2} d2 = {'a':3, 'd':4} cm = Chainmap(d1, d2) assert cm['a'] == 1 assert cm['b'] == 2 assert cm['d'] == 4 try: print cm['f'] except KeyError: pass else: raise Exception('Did not raise KeyError for missing key') assert 'a' in cm and 'b' in cm and 'd' in cm assert cm.get('a', 10) == 1 assert cm.get('b', 20) == 2 assert cm.get('d', 30) == 4 assert cm.get('f', 40) == 40

The underlying mapping need only define __getitem__ and raise KeyError when a key is not found.

This is a general purpose routine applicable in many contexts. Something similar was used to implement string.Template in Py2.4.