Mar*_*cin 5 python dictionary facade
由于这里关于这个主题的许多问题证明了这一点,所以拿一本字典是一个非常常见的任务,有一个相当不错的解决方案:
{k:v for k,v in dict.viewitems() if some_test(k,v)}
Run Code Online (Sandbox Code Playgroud)
但是这会创建一个新的字典,并带有自己的映射.对于许多操作,只有原始字典的不可变视图(即它不支持视图上的赋值或删除操作)会很好.实现这样的类型可能很容易,但是增加本地实用程序类并不好.
所以,我的问题是:是否有内置的方式来获得这样的"子集视图"?或者是否有第三方库(最好通过PyPi提供)提供这种实用程序的良好实现?
似乎没有内置的方法来获取字典的视图。最简单的解决方法似乎是 Jochen 的方法。我稍微修改了他的代码以使其适合我的目的:
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}
Run Code Online (Sandbox Code Playgroud)
所以d2
像除了打印,由于不同的各方面字典的行为__repr__()
方式。继承自dict
to get__repr__()
将需要重新实现每个方法,就像对collections.OrderedDict
. 如果一个人想只是一个只读视图,可以继承collections.Mapping
和保存的执行__setitem__()
和__delitem__()
。我发现DictView
从中选择参数self.__dict__
并以紧凑的形式传递它们很有用。
这很容易实现:
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)
Run Code Online (Sandbox Code Playgroud)