簡體   English   中英

collections.ChainMap的目的是什么?

[英]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

它是由動機這個問題 ,並通過公開這一個 (不PEP創建)。

據我所知,它是一個替代,有一個額外的字典,並使用update() s維護它。

問題是:

  • ChainMap涵蓋哪些用例?
  • ChainMap有沒有真實世界的例子?
  • 它是否用於切換到python3的第三方庫?

額外問題:有沒有辦法在Python2.x上使用它?


我在Raymond Hettinger的“ Transforming Code into Beautiful, Idiomatic Python PyCon Transforming Code into Beautiful, Idiomatic Python聽說過它,我想將它添加到我的工具包中,但我不知道何時應該使用它。

我喜歡@ b4hand的例子,實際上我在過去使用的類似ChainMap的結構(但不是ChainMap本身)中使用了他提到的兩個目的:多層配置覆蓋和變量堆棧/范圍仿真。

我想指出ChainMap另外兩個動機/優點/差異,與使用dict-update循環相比,因此只存儲“最終”版本“:

  1. 更多信息:由於ChainMap結構是“分層的”,它支持回答問題:我是否獲得“默認”值或被覆蓋的值? 什么是原始(“默認”)值? 在什么級別上覆蓋了值(借用@ b4hand的配置示例:user-config或命令行覆蓋)? 使用簡單的詞典,回答這些問題所需的信息已經丟失。

  2. 速度權衡:假設你有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看起來像是一種非常簡單的抽象。 對於一個非常特殊的問題,這是一個很好的解決方案。 我提出這個用例。

如果你有:

  1. 多個映射(例如,dicts)
  2. 這些映射中的一些鍵重復(相同的鍵可以出現在多個映射中,但不是所有鍵都出現在所有映射中的情況)
  3. 希望在“最高優先級”映射中訪問密鑰值的消費應用程序,其中對於任何給定密鑰的所有映射都存在總排序(即,映射可能具有相同的優先級,但僅在已知這些映射中沒有密鑰的重復)(在Python應用程序中,包可以存在於同一目錄中(相同的優先級)但必須具有不同的名稱,因此,根據定義,該目錄中的符號名稱不能重復。)
  4. 消費應用程序不需要更改密鑰的值
  5. 同時映射必須保持其獨立的身份,並且可以由外部力量異步地改變
  6. 並且映射足夠大,價格足以訪問,或者在應用程序訪問之間經常更改,每次應用程序需要時計算投影(3)的成本是您應用程序的重要性能問題...

然后,您可以考慮使用鏈圖來創建映射集合的視圖。

但這都是事后的理由。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM