Python创建自己的字典子集的字典视图

发布于 2025-01-06 23:23:21 字数 340 浏览 3 评论 0原文

正如 SO 上关于该主题的许多问题所证明的那样,获取字典的一部分是一项非常常见的任务,并且有一个相当好的解决方案:

{k:v for k,v in dict.viewitems() if some_test(k,v)}

但这会创建一个具有自己的映射的新字典。对于许多操作来说,最好有一个原始字典的不可变视图(即它不支持视图上的赋值或删除操作)。实现这样的类型可能很容易,但是本地实用程序类的激增并不好。

所以,我的问题是:是否有一种内置的方法来获取这样的“子集视图”?或者是否有第三方库(最好通过 PyPi 提供)可以提供此类实用程序的良好实现?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

月依秋水 2025-01-13 23:23:21

似乎没有内置的方法来获取字典的视图。最简单的解决方法似乎是 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}

因此,由于不同的 __repr__() 方法,因此 d2 在除打印之外的所有方面都表现得像字典。从 dict 继承来获取 __repr__() 需要重新实现每个方法,就像 collections.OrderedDict 所做的那样。如果只想要一个只读视图,可以继承collections.Mapping并保存__setitem__()__delitem__()的实现。我发现 DictView 对于从 self.__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.

哑剧 2025-01-13 23:23:21

这很容易实现:

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)

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)
多像笑话 2025-01-13 23:23:21

为了澄清语义,您正在考虑这样的事情:?

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

如果是这样,那么我不知道有这样的第三方课程。如果您想让其余方法的实现更容易一些,您可以考虑使用“UserDict”作为基类,它基本上只是字典的包装器(“UserDict.data”属性用于存储包装的字典) 。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文