Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python中使词典只读_Python_Dictionary - Fatal编程技术网

如何在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')