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”版本:

  1. 更多信息:因为ChainMap结构是“分层”的,所以它支持回答这样的问题:我是否获得“默认”值或重写的值? 什么是原始(“默认”)值? 在什么水平的价值被覆盖(借用@ b4hand的configuration示例:用户configuration或命令行覆盖)? 用一个简单的字典,回答这些问题所需的信息已经失去了。

  2. 速度折衷:假设你有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。 我提出这个用例。

如果你有:

  1. 多个映射(例如,字典)
  2. 这些映射中的某些键的重复(相同的键可以出现在多个映射中,但不是所有键都出现在所有映射中的情况)
  3. 一个消费应用程序希望访问“最高优先级”映射中的键的值,其中在任何给定键的所有映射上存在全部sorting(也就是说,映射可以具有相同的优先级,但是只有在知道在这些映射中没有键的重复)(在Python应用程序中,包可以存在于相同的目录(相同的优先级)中,但是必须具有不同的名称,因此根据定义,该目录中的符号名称不能重复。
  4. 消费应用程序不需要更改密钥的值
  5. 而同时映射必须保持其独立的身份,并可以通过外力asynchronous改变
  6. 并且映射足够大,足够昂贵以便在应用程序访问之间进行访问或更改,计算投影(3)的成本每次您的应用程序需要时都是您的应用程序的重要性能问题。

然后,您可以考虑使用链表来创build映射集合的视图。

但这都是事后的理由。 Python家伙有一个问题,在代码的上下文中提出了一个好的解决scheme,然后做了一些额外的工作来抽象他们的解决scheme,所以我们可以使用它,如果我们select。 给他们更多的权力。 但是,是否适合您的问题取决于您自己决定。

为了不完美地回答你的:

奖金的问题:有没有办法在Python2.x上使用它?

 from ConfigParser import _Chainmap as ChainMap 

但请记住,这不是一个真正的ChainMap ,它从DictMixininheritance,只定义:

 __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) 

它的实施似乎也不是特别有效。