Python create own dict view of subset of dictionary

后端 未结 3 740
情深已故
情深已故 2021-01-13 05:32

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         


        
相关标签:
3条回答
  • 2021-01-13 06:13

    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).

    0 讨论(0)
  • 2021-01-13 06:21

    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.

    0 讨论(0)
  • 2021-01-13 06:25

    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)
    
    0 讨论(0)
提交回复
热议问题