Python 除了 dict 字典类型, 还有相关的字典扩展类型, 包括MappingProxyType 只读字典, defaultdict 缺省字典和 ChainMap
MappingProxyType 只读字典
MappingProxyType 为普通字典提供只读视图
除了无法修改, 只读字典与普通字典的功能一致
- 只读字典运算:
>>> from types import MappingProxyType
>>> w = {'ide': 'PyCharm'}
>>> r = MappingProxyType(w)
>>> len(r)
1
>>> r['ide']
'PyCharm'
# 无法修改
>>> r['language'] = 'Python'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'mappingproxy' object does not support item assignment
# 成员运算
>>> 'ide' in r
True
# 比较运算, 与原字典相等
>>> r == w
True
# 并集(Python 3.9 新增), 因本身不可修改, 返回了新的字典
>>> r | {'language': 'Python'}
{'ide': 'PyCharm', 'language': 'Python'}
更新原字典后, 只读字典会同步修改
>>> w['version'] = '3.9'
>>> r
mappingproxy({'ide': 'PyCharm', 'version': '3.9'})
- 只读字典方法:
>>> r.get('language', 'Go')
'Go'
# 只读字典也支持 keys(), values(), items() 方法
>>> for k, v in r.items():
... print(f"{k}:{v}")
...
ide:PyCharm
version:3.9
defaultdict 缺省字典
当字典的键不存在时, defaultdict 使用工厂函数的返回值作为这个键对应的值
常用的工厂函数有 int
, list
等, 不传参数时返回一个工厂默认值
>>> int()
0
>>> list()
[]
使用缺省字典
>>> from collections import defaultdict
>>> dd = defaultdict(list)
# 键不存在时, 调用工厂函数(没有参数的调用), 将返回值(空列表)作为字典的值
>>> dd['other']
[]
>>> dd['ide'].append('VSCode')
>>> dd
defaultdict(<class 'list'>, {'other': [], 'ide': ['VSCode']})
在底层 defaultdict 比普通字典 dict 多实现了 __missing__ 方法, 在字典的键不存在时, 该方法会被调用
ChainMap
ChainMap 将多个字典组成一个映射数据结构, 在使用上与字典一致
- 通过键访问值时, 优先返回第一个包含该键的字典的值
- 修改 ChainMap 时, 仅更新第一个字典
>>> from collections import ChainMap
>>> d_1 = {'one': 1, 'two': 2}
>>> d_2 = {'two': 0, 'six': 6}
>>> d = ChainMap(d_1, d_2)
# 访问 ChainMap
>>> d['two']
2
# 修改 ChainMap
>>> d['ten'] = 10
# 实际修改了第一个字典
>>> d_1
{'one': 1, 'two': 2, 'ten': 10}
# 与普通字典一样的使用
>>> list(d.keys())
['two', 'six', 'one', 'ten']
>>> list(d.values())
[2, 6, 1, 10]
>>> d.get('other', 0)
0
在底层 ChainMap 的 maps 属性保存了所有的字典
>>> d.maps
[{'one': 1, 'two': 2, 'ten': 10}, {'two': 0, 'six': 6}]