怎么创建一个不可变的字典?
types.MappingProxyType

概述


初学python时,我们都喜欢用list和dict来存储数据,增删改都很方便和快捷。因为初学时从不会考虑性能和其他很多不确定的因素。
在python中在适当的地方使用tuple是一个很好的习惯,至于为什么可参看我之前的文章tuple和list比较

但是如果想存储k-v数据时,我们就不得不使用dict。但又想dict不可变该怎么办呢?

怎么创建一个不可变的字典


  • 字典的增删改
jerry_info = {'name': 'jerry', 'age': 28, 'address': 'shanghai'}
jerry_info['age'] = 30
jerry_info.update(address='beijing')
jerry_info['salary'] = 999999
jerry_info.update({'job': 'engineer'})
print(jerry_info)
jerry_info.pop('address')
print(jerry_info)
----------------------
{'name': 'jerry', 'age': 30, 'address': 'beijing', 'salary': 999999, 'job': 'engineer'}
{'name': 'jerry', 'age': 30, 'salary': 999999, 'job': 'engineer'}
  • 不可变(只读)的dict
    有时候,我们在项目中用字典来存储一些数据,但又不希望别人对其修改,或者担心别人误修改到,造成麻烦。这时,我们就可以用到types.MappingProxyType
from types import MappingProxyType

jerry_info_data = {'name': 'jerry', 'age': 28, 'address': 'shanghai'}
jerry_info = MappingProxyType(jerry_info_data)
# jerry_info['age'] = 30  # TypeError: 'mappingproxy' object does not support item assignment
print(jerry_info)
# 如果真想修改,可尝试修改jerry_info_data,则可通过修改原始字典jerry_info,则该修改会反映到 MappingProxyType 处理过的对象上面
jerry_info_data['age'] = 30  # 在项目中,如果不想被修改,就不要暴露jerry_info_data出来,或直接定义jerry_info = MappingProxyType({'name': 'jerry', 'age': 28, 'address': 'shanghai'})
print(jerry_info)
---------------------------
{'name': 'jerry', 'age': 28, 'address': 'shanghai'}
{'name': 'jerry', 'age': 30, 'address': 'shanghai'}
class Info:
    def __init__(self, name, age):
        self.__info = {'name': name, 'age': age}

    @property
    def info(self):
        return MappingProxyType(self.__info)
    
    # 只提供修改年龄的接口
    @info.setter
    def info(self, age):
        self.__info['age'] = age


jerry = Info('jerry', 28)
jerry_info = jerry.info
print(jerry_info)
# jerry_info['age'] = 30 # TypeError: 'mappingproxy' object does not support item assignment
jerry.info = 30
print(jerry_info)
------------------
{'name': 'jerry', 'age': 28}
{'name': 'jerry', 'age': 30}