[英]What is the purpose of collections.ChainMap?
在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
據我所知,它是一個替代,有一個額外的字典,並使用update()
s維護它。
問題是:
ChainMap
涵蓋哪些用例? ChainMap
有沒有真實世界的例子? 額外問題:有沒有辦法在Python2.x上使用它?
我在Raymond Hettinger的“ Transforming Code into Beautiful, Idiomatic Python
PyCon Transforming Code into Beautiful, Idiomatic Python
聽說過它,我想將它添加到我的工具包中,但我不知道何時應該使用它。
我喜歡@ 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)
最壞情況。 在這里查看更多細節。
我可以看到將ChainMap
用於配置對象,其中您有多個配置范圍,如命令行選項,用戶配置文件和系統配置文件。 由於查找按構造函數參數中的順序排序,因此您可以覆蓋較低范圍的設置。 我沒有親自使用或看過使用過ChainMap
,但這並不奇怪,因為它是標准庫的最新成員。
如果您嘗試自己實現詞法范圍,那么在模擬堆棧幀時,如果您推送和彈出變量綁定,它也可能很有用。
ChainMap的標准庫文檔提供了幾個示例以及第三方庫中類似實現的鏈接。 具體來說,它命名Django的Context類和Enthought的MultiContext類 。
我會抓住這個:
Chainmap看起來像是一種非常簡單的抽象。 對於一個非常特殊的問題,這是一個很好的解決方案。 我提出這個用例。
如果你有:
然后,您可以考慮使用鏈圖來創建映射集合的視圖。
但這都是事后的理由。 Python人員遇到了問題,在他們的代碼環境中提出了一個很好的解決方案,然后做了一些額外的工作來抽象他們的解決方案,以便我們可以選擇使用它。 給他們更多的力量。 但是,是否適合您的問題由您決定。
不完美地回答你:
額外問題:有沒有辦法在Python2.x上使用它?
from ConfigParser import _Chainmap as ChainMap
但請記住,這不是真正的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)
它的實施似乎也不是特別有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.