collections的目的是什么?链接地图?
在Python 3.3中,一个ChainMap
类被添加到collections
模块中:
ChainMap类提供了快速链接多个映射,以便它们可以被视为一个单元。 通常比创build新的字典和运行多个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
这个问题的动机是这个问题的公开(没有PEP
创build)。
据我所知,这是一个替代有一个额外的字典和维护与update()
。
问题是:
-
ChainMap
覆盖哪些用例? - 有什么现实的
ChainMap
例子? - 它是否用于切换到python3的第三方库?
奖金的问题:有没有办法在Python2.x上使用它?
我听说过Transforming Code into Beautiful, Idiomatic Python
PyCon谈话,Raymond Hettinger,我想把它添加到我的工具包中,但是我不了解何时应该使用它。
我喜欢@ b4hand的例子,实际上我曾经使用了过去的ChainMap类结构(但不是ChainMap本身),他提到了两个目的:多层configuration覆盖和可变堆栈/范围模拟。
我想指出ChainMap
另外两个动机/优势/差异,与使用dict-update循环相比,只存储“final”版本:
-
更多信息:因为ChainMap结构是“分层”的,所以它支持回答这样的问题:我是否获得“默认”值或重写的值? 什么是原始(“默认”)值? 在什么水平的价值被覆盖(借用@ b4hand的configuration示例:用户configuration或命令行覆盖)? 用一个简单的字典,回答这些问题所需的信息已经失去了。
-
速度折衷:假设你有
N
层,最多有M
键,构造一个ChainMap需要O(N)
,每个查找O(N)
最差的情况下,而使用更新循环构造一个字典需要O(NM)
和每个查找O(1)
。 这意味着如果您经常构build并且每次只执行一些查找,或者如果M
很大,ChainMap的懒惰构build方法对您有利。
(2)中的分析假定字典访问是O(1)
,实际上平均为O(1)
, O(M)
最差。 在这里看到更多细节。
我可以看到使用ChainMap
的configuration对象,你有多个configuration范围,如命令行选项,用户configuration文件和系统configuration文件。 由于查找按构造函数参数中的顺序sorting,因此可以覆盖较低范围的设置。 我没有亲自使用过或看过使用过的ChainMap
,但这并不奇怪,因为它是标准库的新增function。
如果您试图自己实现一个词法范围,那么在您推送和popupvariables绑定的情况下模拟堆栈帧也可能是有用的。
ChainMap的标准库文档给出了几个例子,并链接到第三方库中类似的实现。 具体来说,它命名Django的Context类和Enthought的MultiContext类 。
我会采取这样的裂缝:
Chainmap看起来像一个非常公平的抽象。 这是一个非常专业的问题的一个很好的解决scheme。 我提出这个用例。
如果你有:
- 多个映射(例如,字典)
- 这些映射中的某些键的重复(相同的键可以出现在多个映射中,但不是所有键都出现在所有映射中的情况)
- 一个消费应用程序希望访问“最高优先级”映射中的键的值,其中在任何给定键的所有映射上存在全部sorting(也就是说,映射可以具有相同的优先级,但是只有在知道在这些映射中没有键的重复)(在Python应用程序中,包可以存在于相同的目录(相同的优先级)中,但是必须具有不同的名称,因此根据定义,该目录中的符号名称不能重复。
- 消费应用程序不需要更改密钥的值
- 而同时映射必须保持其独立的身份,并可以通过外力asynchronous改变
- 并且映射足够大,足够昂贵以便在应用程序访问之间进行访问或更改,计算投影(3)的成本每次您的应用程序需要时都是您的应用程序的重要性能问题。
然后,您可以考虑使用链表来创build映射集合的视图。
但这都是事后的理由。 Python家伙有一个问题,在代码的上下文中提出了一个好的解决scheme,然后做了一些额外的工作来抽象他们的解决scheme,所以我们可以使用它,如果我们select。 给他们更多的权力。 但是,是否适合您的问题取决于您自己决定。
为了不完美地回答你的:
奖金的问题:有没有办法在Python2.x上使用它?
from ConfigParser import _Chainmap as ChainMap
但请记住,这不是一个真正的ChainMap
,它从DictMixin
inheritance,只定义:
__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)
它的实施似乎也不是特别有效。