Python: Freeze dict keys after creation
本问题已经有最佳答案,请猛点这里访问。
是否可以在创建后"冻结"python dict,以便不可能向其添加新键?只能更改现有的键值。
如果没有,您如何知道何时更改现有的keyvalue对以及何时添加新的keyvalue对?
可能是这样的:
1 2 3 4 5 6 7 8 9 10 | class FreezableDict (dict): __frozen = False def freeze (self): self.__frozen = True def __setitem__ (self, key, value): if self.__frozen and key not in self: raise ValueError('Dictionary is frozen') super().__setitem__(key, value) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> x = FreezableDict({'foo': 'bar', 'baz': 'bla'}) >>> x {'baz': 'bla', 'foo': 'bar'} >>> x['asdf'] = 'fdsa' >>> x {'asdf': 'fdsa', 'baz': 'bla', 'foo': 'bar'} >>> x.freeze() >>> x['hello'] = 'world' Traceback (most recent call last): File"<pyshell#20>", line 1, in <module> x['hello'] = 'world' File"<pyshell#13>", line 8, in __setitem__ raise ValueError('Dictionary is frozen') ValueError: Dictionary is frozen |
请注意,您也可能希望覆盖其他方法,包括
如果您对完全锁定字典感兴趣,可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | >>> x = {'foo': 'bar'} >>> y = types.MappingProxyType(x) >>> y mappingproxy({'foo': 'bar'}) >>> x['baz'] = 'bla' >>> y mappingproxy({'baz': 'bla', 'foo': 'bar'}) >>> y['hello'] = 'world' Traceback (most recent call last): File"<pyshell#55>", line 1, in <module> y['hello'] = 'world' TypeError: 'mappingproxy' object does not support item assignment >>> del x >>> y mappingproxy({'baz': 'bla', 'foo': 'bar'}) |
或者只是在一行中,从来没有引用过原始字典:
1 2 3 4 5 6 7 8 | >>> x = types.MappingProxyType({'foo': 'bar', 'baz': 'bla'}) >>> x mappingproxy({'baz': 'bla', 'foo': 'bar'}) >>> x['hello'] = 'world' Traceback (most recent call last): File"<pyshell#60>", line 1, in <module> x['hello'] = 'world' TypeError: 'mappingproxy' object does not support item assignment |
这是不可能的"香草"口述。你可能会想亚类
未测试代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | class FrozenKeyDict(collections.MutableMapping): """Mapping which doesn't allow keys to be added/deleted. It does allow existing key/value pairs to be modified. """ def __init__(self, *args, **kwargs): self._frozen = False self._dict = {} super(FrozenKeyDict, self).__init__(*args, **kwargs) self._frozen = True def __getitem__(self, key): return self._dict[key] def __setitem__(self, key, value): if self._frozen and key not in self._dict: raise KeyError('must be one of %s' % list(self)) self._dict[key] = value def __delitem__(self, key): # modify to suit your needs ... raise KeyError('Removing keys not supported') def __iter__(self): return iter(self._dict) def __len__(self): return len(self._dict) |