ChainMap对象-collections- 容器数据类型(27)Python语言(必读进阶学习教程)(参考资料)
版本3.3中的新功能。
ChainMap
提供了一个类,用于快速链接多个映射,以便将它们视为一个单元。它通常比创建新词典和运行多个update()
调用快得多。
该类可用于模拟嵌套作用域,在模板中很有用。
- class
collections.
ChainMap
(* maps ) - 将
ChainMap
多个dicts或其他映射组合在一起以创建单个可更新视图。如果未指定映射,则提供单个空字典,以便新链始终至少具有一个映射。底层映射存储在列表中。该列表是公共的,可以使用maps属性访问或更新。没有其他州。
查找会连续搜索基础映射,直到找到密钥。相反,写入,更新和删除仅对第一个映射进行操作。
A
ChainMap
通过引用合并了底层映射。因此,如果其中一个底层映射得到更新,那么这些更改将反映在其中ChainMap
。支持所有常用的字典方法。此外,还有一个 maps属性,一个用于创建新子上下文的方法,以及一个用于访问除第一个映射之外的所有映射的属性:
maps
- 用户可更新的映射列表。该列表从首次搜索到最后搜索排序。它是唯一存储的状态,可以进行修改以更改搜索的映射。该列表应始终包含至少一个映射。
new_child
(m =无)- 返回
ChainMap
包含新映射的新映射,后跟当前实例中的所有映射。如果m
指定,则它将成为映射列表前面的新映射; 如果未指定,则使用空的dict,以便调用d.new_child()
等效于:。此方法用于创建可在不更改任何父映射中的值的情况下更新的子上下文。ChainMap({}, *d.maps)
版本3.4中已更改:
m
添加了可选参数。
parents
- 返回new的属性,
ChainMap
包含当前实例中除第一个之外的所有映射。这对于在搜索中跳过第一个地图很有用。用例类似于嵌套作用域中nonlocal
使用的 关键字。用例也与内置函数的用例相同 。引用相当于:。super()
d.parents
ChainMap(*d.maps[1:])
也可以看看
- Enthought CodeTools包中的MultiContext类具有支持写入链中任何映射的选项。
- Django 用于模板化的Context类是一个只读的映射链。它还具有类似于
new_child()
方法和parents
属性的上下文推送和弹出功能 。 - 所述嵌套上下文配方具有选项来控制写入和其它突变是否只适用于第一映射或链中的任何映射。
- 一个极为简化的Chainmap只读版本。
ChainMap
例子和食谱
本节介绍使用链式地图的各种方法。
模拟Python内部查找链的示例:
import builtins
pylookup = ChainMap(locals(), globals(), vars(builtins))
让用户指定的命令行参数优先于环境变量的示例,而环境变量优先于默认值:
import os, argparse
defaults = {'color': 'red', 'user': 'guest'}
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
command_line_args = {k:v for k, v in vars(namespace).items() if v}
combined = ChainMap(command_line_args, os.environ, defaults)
print(combined['color'])
print(combined['user'])
使用ChainMap
类来模拟嵌套上下文的示例模式:
c = ChainMap() # Create root context
d = c.new_child() # Create nested child context
e = c.new_child() # Child of c, independent from d
e.maps[0] # Current context dictionary -- like Python's locals()
e.maps[-1] # Root context -- like Python's globals()
e.parents # Enclosing context chain -- like Python's nonlocals
d['x'] # Get first key in the chain of contexts
d['x'] = 1 # Set value in current context
del d['x'] # Delete from current context
list(d) # All nested values
k in d # Check all nested values
len(d) # Number of nested values
d.items() # All nested items
dict(d) # Flatten into a regular dictionary
该ChainMap
班不仅使更新(写入和删除),以在链中的第一个映射,同时查找将搜索上满链。但是,如果需要深度写入和删除,则很容易创建一个子类来更新链中更深层次的键:
class DeepChainMap(ChainMap):
'Variant of ChainMap that allows direct updates to inner scopes'
def __setitem__(self, key, value):
for mapping in self.maps:
if key in mapping:
mapping[key] = value
return
self.maps[0][key] = value
def __delitem__(self, key):
for mapping in self.maps:
if key in mapping:
del mapping[key]
return
raise KeyError(key)
>>> d = DeepChainMap({'zebra': 'black'}, {'elephant': 'blue'}, {'lion': 'yellow'})
>>> d['lion'] = 'orange' # update an existing key two levels down
>>> d['snake'] = 'red' # new keys get added to the topmost dict
>>> del d['elephant'] # remove an existing key one level down
>>> d # display result
DeepChainMap({'zebra': 'black', 'snake': 'red'}, {}, {'lion': 'orange'})