我有一个类:
class A:
def __init__(self):
self.data = {}
在某些时刻我想禁止self.data
字段修改。
我在PEP-416 rejection notice读到有很多方法可以做到这一点。所以我想找到它们是什么。
我试过了:
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)
是一种选择,但我认为可以存在其他选项。
由于
答案 0 :(得分:29)
import collections
class DictWrapper(collections.Mapping):
def __init__(self, data):
self._data = data
def __getitem__(self, key):
return self._data[key]
def __len__(self):
return len(self._data)
def __iter__(self):
return iter(self._data)
HTH,
答案 1 :(得分:22)
这是快速(浅)只读字典的完整实现:
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__
答案 2 :(得分:6)
很简单,你只需覆盖默认的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
以及其他所需的方法。只是玩弄它。
答案 3 :(得分:0)
怎么样?这是@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
但是不确定性能。我在一个真实的项目https://github.com/patarapolw/AnkiTools/blob/master/AnkiTools/tools/defaults.py
中使用了它答案 4 :(得分:0)
最好的方法是像这样从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.data
来更新字典的内部方法。