如何在Python中使词典只读
我有一门课,像:如何在Python中使词典只读,python,dictionary,Python,Dictionary,我有一门课,像: class A: def __init__(self): self.data = {} 在某个时刻,我想禁止self.data字段修改 我读到有很多方法可以做到这一点。所以我想知道它们是什么 我试过这个: a = A() a.data = types.MappingProxyType(a.data) 这应该行得通,但首先是python3.3+,其次,当我多次执行此“禁止”操作时,我会得到以下结果: >>> a.data = type
class A:
def __init__(self):
self.data = {}
在某个时刻,我想禁止self.data
字段修改
我读到有很多方法可以做到这一点。所以我想知道它们是什么
我试过这个:
a = A()
a.data = types.MappingProxyType(a.data)
这应该行得通,但首先是python3.3+,其次,当我多次执行此“禁止”操作时,我会得到以下结果:
>>> a.data = types.MappingProxyType(a.data)
>>> a.data = types.MappingProxyType(a.data)
>>> a.data
mappingproxy(mappingproxy({}))
尽管只获取mappingproxy({})
要好得多,因为我将多次“禁止”。检查isinstance(MappingProxyType)
是一个选项,但我认为还可以存在其他选项
非常简单,您只需覆盖默认dict的方法即可
以下是一个例子:
class ReadOnlyDict(dict):
__readonly = False
def readonly(self, allow=1):
"""Allow or deny modifying dictionary"""
self.__readonly = bool(allow)
def __setitem__(self, key, value):
if self.__readonly:
raise TypeError, "__setitem__ is not supported"
return dict.__setitem__(self, key, value)
def __delitem__(self, key):
if self.__readonly:
raise TypeError, "__delitem__ is not supported"
return dict.__delitem__(self, key)
顺便说一句,您还可以删除.pop
、.update
和其他需要的方法。随便玩玩吧。使用例如
这是快速(浅)只读dict的完整实现:
class ReadOnlyDict(dict):
def __readonly__(self, *args, **kwargs):
raise RuntimeError("Cannot modify ReadOnlyDict")
__setitem__ = __readonly__
__delitem__ = __readonly__
pop = __readonly__
popitem = __readonly__
clear = __readonly__
update = __readonly__
setdefault = __readonly__
del __readonly__
怎么样?这是@mouad答案的更新
import json
from collections import OrderedDict
from collections.abc import Mapping
class ReadOnlyJsonObject(Mapping):
def __init__(self, data, dumps_kw: dict=None, loads_kw: dict=None):
if dumps_kw is None:
dumps_kw = dict()
if loads_kw is None:
self._loads_kw = dict(object_pairs_hook=OrderedDict)
else:
self._loads_kw = loads_kw
if isinstance(data, str):
self._json_string = data
else:
self._json_string = json.dumps(data, **dumps_kw)
@property
def _data(self):
return json.loads(self._json_string, **self._loads_kw)
def __getitem__(self, key):
return self._data[key]
def __len__(self):
return len(self._data)
def __iter__(self):
return iter(self._data)
def __str__(self):
return self._json_string
不过,我对性能不太确定。我在一个真实的项目中使用了这个最好的方法是从
UserDict
派生如下:
from collections import UserDict
class MyReadOnlyDict(UserDict):
def my_set(self, key, val, more_params):
# do something special
# custom logic etc
self.data[key] = val
def __setitem__(self, key, val):
raise NotImplementedError('This dictionary cannot me updated')
def __delitem__(self, key):
raise NotImplementedError('This dictionary does not allow delete')
此方法的优点是,您的类中仍然可以有内部方法,这些方法可以通过访问
self来更新字典。数据
可能会帮助您frozendict实现看起来相当简单:@codelover没错,我可以用throw NotImplemented
覆盖\uuuSetItem\uuuuuuuuuuuu
。有没有保证在任何python实现中都无法通过任何标准的dict
属性修改键或值?@sshilovsky没有,相反,您可以派生一个用户dict并覆盖任何适用的东西&您可以在任何地方使用它。这回答了您的问题吗?“在某个时刻”你是如何应用这一点的?我猜OP需要对dict进行读写,然后在一段时间后将其冻结。如果他需要,他可以修改它们。这种方法很明显,但并不简单,因为我必须覆盖几乎每个dict
方法,甚至重新实现dict
视图,如.keys()
,.items()
等等,如果Guido在未来的python版本中添加了更多的内容呢?不管怎样,谢谢你的观点,但我希望有更多的答案。这会不会只是使格言本身,而不是包含必要内容的格言不可变?我当前希望使一个表示配置的嵌套dict不可修改。要允许使用copy.copy
和copy.deepcopy
复制它们,您可能需要添加以下两行:\uuuuuuucopy\uuuuu=dict.copy
和\uuuuuu deepcopy\uu dispatch.get(dict)
。虽然测试不多。对,但如何初始化此文件或如何使现有dict使用此文件?ro\u dict=ReadOnlyDict(rw\u dict)
from collections import UserDict
class MyReadOnlyDict(UserDict):
def my_set(self, key, val, more_params):
# do something special
# custom logic etc
self.data[key] = val
def __setitem__(self, key, val):
raise NotImplementedError('This dictionary cannot me updated')
def __delitem__(self, key):
raise NotImplementedError('This dictionary does not allow delete')