代码之家  ›  专栏  ›  技术社区  ›  flakes

不可变字典的可变包装器

  •  0
  • flakes  · 技术社区  · 7 年前

    我在想象一些不可变dict的包装类,它遵循dict契约,对于未更新的值,默认为不可变dict。我看到帖子了 How to “perfectly” override a dict? 我打算利用它来做这个包装。

    在我开始实现这个设计之前,我只想问一个问题:这个结构是否已经由语言提供?或者我怎样才能达到预期的效果?我使用的是Python(3.7)的最新版本,因此可以使用所有可用的语言功能。谢谢!

    2 回复  |  直到 7 年前
        1
  •  2
  •   almiki    7 年前

    看看 collections.ChainMap . 它是多个字典的包装器:所有的写操作都将进入第一个字典,并且查找将按映射的顺序进行搜索。所以我想你可以做些类似的事情:

    modified_map = {}
    mutable_map = collections.ChainMap(modified_map, huge_immutable_map)
    
        2
  •  0
  •   Bailey Parker    7 年前

    假设你用了 frozendict this one :

    class frozendict(collections.Mapping):
        """
        An immutable wrapper around dictionaries that implements the complete :py:class:`collections.Mapping`
        interface. It can be used as a drop-in replacement for dictionaries where immutability is desired.
        """
    
        dict_cls = dict
    
        def __init__(self, *args, **kwargs):
            self._dict = self.dict_cls(*args, **kwargs)
            self._hash = None
    
        def __getitem__(self, key):
            return self._dict[key]
    
        def __contains__(self, key):
            return key in self._dict
    
        def copy(self, **add_or_replace):
            return self.__class__(self, **add_or_replace)
    
        def __iter__(self):
            return iter(self._dict)
    
        def __len__(self):
            return len(self._dict)
    
        def __repr__(self):
            return '<%s %r>' % (self.__class__.__name__, self._dict)
    
        def __hash__(self):
            if self._hash is None:
                h = 0
                for key, value in self._dict.items():
                    h ^= hash((key, value))
                self._hash = h
            return self._hash
    

    如果你想让它变异,你可以直接进入变异 self._dict :

    d = frozendict({'a': 1, 'b': 2})
    d['a'] = 3  # This fails
    mutable_dict = d._dict
    mutable_dict['a'] = 3  # This works
    print(d['a'])
    

    接触到类的受保护成员有点恶心,但我想说没关系,因为你要做的是有点恶心。如果你想要一个可变字典(只是一个 dict 像上面这样的实现。可变和不变的混合体是没有意义的。全部 冻僵 它没有实现突变邓德方法( __setitem__ , __delitem__ 等等)。引擎盖下a 冻僵 由一个正则的,可变的 .

    在我看来,上述方法比你所链接的方法优越。可组合性 冻僵 _dict 属性)比继承(子类化)更容易推理 )在很多情况下。