Как сделать словарь только для чтения в Python
У меня есть класс вроде:
class A:
def __init__(self):
self.data = {}
и в какой-то момент я хочу запретить модификацию полей self.data
.
Я читал в уведомлении об отказе PEP-416, что есть много способов сделать это. Поэтому я хотел бы найти то, что они есть.
Я пробовал это:
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)
- это вариант, но я думаю, что могут существовать другие варианты.
Спасибо
Ответы
Ответ 1
Используйте collections.Mapping
, например.
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)
НТН,
Ответ 2
Это полная реализация read-only 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__
Ответ 3
Очень просто, вы просто переопределяете стандартные методы 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
и другие методы, которые вам нужны. Просто поиграйте с ним.