程序员的保险箱:Python 中的只读映射数据类型
文章目录
- 参考
- 描述
- 只读映射数据类型
-
-
- 映射数据类型
- 只读映射数据类型
- 为什么需要只读映射数据类型?
-
- MappingProxyType
-
-
- 视图
- 共享底层数据结构
-
参考
项目 | 描述 |
---|---|
流畅的 Python | 【巴西】 Luciano Ramalho 著 / 安道 吴珂 译 |
搜索引擎 | Google 、Bing |
描述
项目 | 描述 |
---|---|
Python 解释器 | 3.10.6 |
只读映射数据类型
映射数据类型
映射数据类型是指一种数据结构,该数据结构能够将一个值(即键)映射到另一个值(即值)。在 Python 中,常见的映射数据类型包括字典(dict)、默认字典(defaultdict)、有序字典(OrderedDict)、计数器(Counter)等。
只读映射数据类型
只读映射数据类型是指一种特殊的映射数据类型,它提供了一种只读的访问方式,即不能对映射数据类型进行任何的修改操作。
为什么需要只读映射数据类型?
-
安全性
只读映射数据类型是只读的,不支持修改操作,能够避免误操作或者恶意篡改数据的风险。 -
性能
在多进程或者多线程的场景下,使用只读映射数据类型也能够提高程序的性能。由于只读映射数据类型不支持修改操作,因此不会出现竞争条件,避免了多线程或者多进程的锁竞争,提高了程序的并发性能。 -
线程安全
只读映射数据类型是线程安全的,因为它只允许读取操作,不允许写入操作。多个线程可以同时访问只读映射数据类型,而不会导致数据冲突或竞争条件。这使得只读映射数据类型成为在并发环境中共享数据的一种很好的方式。
MappingProxyType
MappingProxyType 类型为 Python 中的一种内置类型,它是一种只读映射数据类型,允许你将一个可变映射对象封装成一个只读的对象。对此,请参考如下示例:
# 从 Python 标准库 types 中导入 MappingProxyType 数据类型
from types import MappingProxyTyped = {'Name': 'RedHeart', 'Home': 'BinaryMoon'}# 创建 dict 对象 d 的只读映射对象
d_proxy = MappingProxyType(d)# 只读映射对象与 dict 对象十分相似
print(d_proxy)
print(type(d_proxy))# 尝试对只读映射对象进行修改
d_proxy['Home'] = 'TwoMoons' # TypeError
d_proxy['Name'] += 'Made In China' # TypeError
执行效果
在尝试对只读映射对象进行修改时,Python 将抛出异常错误(在本例中抛出了 TypeError 异常错误)。
{'Name': 'RedHeart', 'Home': 'BinaryMoon'}
<class 'mappingproxy'>
视图
只读映射数据类型实际上是原字典类型的只读视图。它提供了一个字典的只读版本,可以对外提供对字典数据的只读访问,同时不允许修改字典数据,从而保证字典数据的安全性。
如果你需要对字典进行修改,可以直接对原字典对象进行修改,修改后的结果将立即反映到视图中。对此,请参考如下示例:
# 从 Python 标准库 types 中导入 MappingProxyType 数据类型
from types import MappingProxyTyped = {'Name': 'RedHeart', 'Home': 'BinaryMoon'}d_proxy = MappingProxyType(d)
print(d_proxy)# 通过原字典对象对字典进行修改
d['Home'] = 'TwoMoons'
d['Name'] += ' (Made In China)'# 原字典的修改已反映到视图中
print(d_proxy)
执行效果
{'Name': 'RedHeart', 'Home': 'BinaryMoon'}
{'Name': 'RedHeart (Made In China)', 'Home': 'TwoMoons'}
共享底层数据结构
在 Python 中,普通字典类型在内部使用哈希表来实现数据的存储和查找,这个哈希表在内存中是一个连续的数组,其中每个元素都是一个哈希桶,用于存储键值对。当我们创建一个只读映射数据类型时,它会引用原字典的哈希表对象,而不会复制一份新的数据结构。这样就可以避免原字典中的数据被不必要地复制多份,从而减少内存的占用和复制的时间开销。
此外,由于只读映射数据类型与原映射数据类型共享底层数据结构,它们之间的数据始终保持一致,这有助于提高程序的安全性和可维护性,避免了多份数据之间的不一致性问题。这对于并发编程和大型项目的开发非常重要,因为它可以减少代码的调试和测试工作量。
注:
Python 的只读映射数据类型与原映射数据类型共享底层数据结构并不意味着两者位于相同的内存空间中。对此,请参考如下示例:
from types import MappingProxyTyped = {'Name': 'RedHeart', 'Home': 'BinaryMoon'}
# 输出 Python dict 实例化对象 d 所处的内存空间对应的内存地址
print(id(d))# 创建 dict 对象 d 的只读映射对象
d_proxy = MappingProxyType(d)
# 输出 d_proxy 所处的内存空间对应的内存地址
print(id(d_proxy))
执行效果
两者所处的内存空间所对应的内存地址并不相同,这意味着两者虽共享底层数据结构,但两者并不位于同一内存空间中。
1889258825984
1889257758464