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 di
To clarify the semantics, you're thinking of something like this:?
class FilteredDictView:
def __init__(self, base_dict, test):
self._base_dict = base_dict
self._test = test
def __getitem__(self, key):
value = self._base_dict[key] # might throw KeyError
if not self._test(key,value):
throw KeyError(key)
return value
# ... implement remaining dict-like-methods ...
If so, then I don't know of any such third party class. If you want to make implementing the remaining methods a little easier, you might look at using "UserDict" as a base class, which is basically just a wrapper for dict (the "UserDict.data" attribute is used to store the wrapped dict).
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.
This is pretty easy to implement:
from collections import Mapping
class FilteredItems(Mapping):
def __init__(self, source, filter):
self.source = source
self.p = filter
def __getitem__(self, key):
x = self.source[key]
if self.p(key,x):
return key,x
else:
raise KeyError(key)
d2 = FilteredItems(d, some_test)