[英]Mutable Wrapper for Immutable Dictionary
Here is the problem; 这是问题所在; I have an immutable dictionary with huge set of items. 我有一本不可变的字典,里面有很多项目。 The key type and the value types contained within this dict are themselves immutable. 该字典中包含的键类型和值类型本身是不可变的。 I would like to be able to mutate this dict (adding/removing/replacing key-value pairs) without having to do a full copy of the dict. 我希望能够更改此字典(添加/删除/替换键值对),而不必完整复制字典。
I am imagining some wrapper class for the immutable dict which adheres to the dict contract, and defaults to the immutable dict for values that have not been updated. 我正在想象一个遵循dict契约的不可变dict的包装器类,对于未更新的值默认为不可变dict。 I see the post How to “perfectly” override a dict? 我看到了如何“完美”地覆盖字典的帖子? which I plan to leverage to make this wrapper. 我计划利用该包装器。
Before I embark on implementing this design I just wanted to ask- is this construct already provided by the language? 在开始实施此设计之前,我只是想问-语言是否已经提供了这种结构? Or how else can I achieve the desired effect? 或者我还能如何达到预期的效果? I am on the latest version of Python (3.7) so I can use all language features available. 我使用的是最新版本的Python(3.7),因此我可以使用所有可用的语言功能。 Thanks! 谢谢!
Take a look at collections.ChainMap
. 看一下collections.ChainMap
。 It's a wrapper around multiple dictionaries: all writes go to the first dictionary, and lookups are searched in order of the maps. 它是围绕多个词典的包装:所有写操作都进入第一个词典,并且按映射顺序搜索查找。 So I think you could just do something like: 因此,我认为您可以执行以下操作:
modified_map = {}
mutable_map = collections.ChainMap(modified_map, huge_immutable_map)
Let's say you used a frozendict
implementation like this one : 假设您使用了像这样的frozendict
实现:
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
If you wanted to mutate it, you could just reach in and mutate self._dict
: 如果您想对其进行变异,则可以进入并变异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'])
It's a little yucky reaching into a class's protected members, but I'd say that's okay because what you're trying to do is a little yucky. 接触到班级受保护的成员有点麻烦,但是我想这没关系,因为您要尝试做的就是有点讨厌。 If you want a mutable dictionary (just a dict
) then use one. 如果您想要可变的字典(仅是dict
),请使用一个。 If you never want to mutate it, use a frozendict
implementation like the one above. 如果您永远不想对其进行突变,请使用上面一种frozendict
实现。 A hyrid of mutable and immutable makes no sense. 如此多变和一成不变的讽刺毫无意义。 All frozendict
does is it doesn't implement the mutation dunder methods ( __setitem__
, __delitem__
, etc.). frozendict
就是不执行dunder突变方法( __setitem__
, __delitem__
等)。 Under the hood a frozendict
is represented by a regular, mutable dict
. 引擎盖下一个frozendict
是由有规律的,可变表示dict
。
The above approach is superior in my view to the one you linked. 在我看来,以上方法优于您所链接的方法。 Composability (having frozendict
have a _dict
property) is much easier to reason about than inheritance (subclassing dict
) in many cases. 组合性(具有frozendict
有_dict
属性)是非常容易的推理不是继承(子类dict
)在许多情况下。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.