Python create own dict view of subset of dictionary
dictionary, facade, python
Solution
There seems to be no builtin way to obtain a view into a dictionary. The easiest workaround appears to be Jochen's approach. I adapted his code slightly to make it work for my purposes:
from collections import MutableMapping
class DictView(MutableMapping):
def __init__(self, source, valid_keys):
self.source, self.valid_keys = source, valid_keys
def __getitem__(self, key):
if key in self.valid_keys:
return self.source[key]
else:
raise KeyError(key)
def __len__(self):
return len(self.valid_keys)
def __iter__(self):
for key in self.valid_keys:
yield key
def __setitem__(self, key, value):
if key in self.valid_keys:
self.source[key] = value
else:
raise KeyError(key)
def __delitem__(self, key):
self.valid_keys.remove(key)
d = dict(a=1, b=2, c=3)
valid_keys = ['a', 'c']
d2 = DictView(d, valid_keys)
d2['a'] = -1 # overwrite element 'a' in source dictionary
print d # prints {'a': -1, 'c': 3, 'b': 2}
So `d2` behaves like a dictionary in all aspects except for printing, due to the different `__repr__()` method. Inheriting from `dict` to get `__repr__()` would require reimplementation of each and every method, as is done for `collections.OrderedDict`. If one wants only a readonly view, one can inherit from `collections.Mapping` and save the implementation of `__setitem__()` and `__delitem__()`. I find `DictView` useful to select parameters from `self.__dict__` and pass them on in a compact form.
Problem
As the many questions on the topic here on SO attest, taking a slice of a dictionary is a pretty common task, with a fairly nice solution: ``` {k:v for k,v in dict.viewitems() if some_test(k,v)} ``` But that creates a new dictionary, with its own mappings. For many operations, it would be nice to just have an immutable view of the original dict (i.e. it does not support assignment or deletion operations on the view). Implementing such a type is probably easy, but it's not good to have a proliferation of local utility classes. So, my question is: is there a built-in way of obtaining such a "subset view"? Or is there a third-party library (preferably available via PyPi) that provides a good implementation of such a utility?