ale*_*cxe 60 python collections dictionary data-structures python-3.x
在Python 3.3中,一个ChainMap类被添加到collections模块中:
提供了一个ChainMap类,用于快速链接多个映射,以便将它们视为一个单元.它通常比创建新字典和运行多个update()调用快得多.
例:
>>> from collections import ChainMap
>>> x = {'a': 1, 'b': 2}
>>> y = {'b': 10, 'c': 11}
>>> z = ChainMap(y, x)
>>> for k, v in z.items():
print(k, v)
a 1
c 11
b 10
Run Code Online (Sandbox Code Playgroud)
据我所知,它是一个替代,有一个额外的字典,并用update()s 维护它.
问题是:
ChainMap包括哪些用例?ChainMap吗?额外问题:有没有办法在Python2.x上使用它?
我在Transforming Code into Beautiful, Idiomatic PythonRayCon Hettinger的PyCon演讲中听说过它,我想将它添加到我的工具包中,但我不知道何时应该使用它.
shx*_*hx2 61
我喜欢@ b4hand的例子,实际上我在过去使用的类似ChainMap的结构(但不是ChainMap本身)中使用了他提到的两个目的:多层配置覆盖和变量堆栈/范围仿真.
ChainMap与使用dict-update循环相比,我想指出另外两个动机/优点/差异,因此只存储"最终"版本":
更多信息:由于ChainMap结构是"分层的",它支持回答问题:我是否获得"默认"值或被覆盖的值?什么是原始("默认")值?在什么级别上覆盖了值(借用@ b4hand的配置示例:user-config或命令行覆盖)?使用简单的词典,回答这些问题所需的信息已经丢失.
速度权衡:假设你有N层和M每个键中最多的键,构造一个ChainMap O(N),每个查找O(N)最坏情况[*],而使用更新循环构造一个dict O(NM)并进行每次查找O(1).这意味着如果你经常构造并且每次只执行一些查找,或者如果M很大,ChainMap的懒惰构造方法对你有利.
[*](2)中的分析假定dict-access是O(1),实际上它是O(1)平均的,O(M)最坏的情况.在这里查看更多细节.
b4h*_*and 36
我可以看到ChainMap用于配置对象,其中有多个配置范围,如命令行选项,用户配置文件和系统配置文件.由于查找按构造函数参数中的顺序排序,因此您可以覆盖较低范围的设置.我没有亲自使用或看到过ChainMap使用过,但这并不奇怪,因为它是标准库的最新版本.
如果您尝试自己实现词法范围,那么在模拟堆栈帧时,如果您推送和弹出变量绑定,它也可能很有用.
ChainMap的标准库文档提供了几个示例以及第三方库中类似实现的链接.具体来说,它命名Django的Context类和Enthought的MultiContext类.
我会抓住这个:
Chainmap看起来像是一种非常简单的抽象.对于一个非常特殊的问题,这是一个很好的解决方案.我提出这个用例.
如果你有:
然后,您可以考虑使用链图来创建映射集合的视图.
但这都是事后的理由.Python人员遇到了问题,在他们的代码环境中提出了一个很好的解决方案,然后做了一些额外的工作来抽象他们的解决方案,以便我们可以选择使用它.给他们更多的力量.但是,是否适合您的问题由您决定.
不完美地回答您的问题:
额外的问题:是否可以在Python2.x上使用它?
from ConfigParser import _Chainmap as ChainMap
Run Code Online (Sandbox Code Playgroud)
但是请记住,这不是真实的ChainMap,它继承自DictMixin并且仅定义:
__init__(self, *maps)
__getitem__(self, key)
keys(self)
# And from DictMixin:
__iter__(self)
has_key(self, key)
__contains__(self, key)
iteritems(self)
iterkeys(self)
itervalues(self)
values(self)
items(self)
clear(self)
setdefault(self, key, default=None)
pop(self, key, *args)
popitem(self)
update(self, other=None, **kwargs)
get(self, key, default=None)
__repr__(self)
__cmp__(self, other)
__len__(self)
Run Code Online (Sandbox Code Playgroud)
它的实现似乎也不是特别有效。