Python編程:換種方式用字典之鏈?zhǔn)接成洌–hainMap),盤(pán)它!
前言
集合是專(zhuān)門(mén)的容器數(shù)據(jù)類(lèi)型(Container Datatype),可以替代Python的通用內(nèi)置容器,如dict、list、set和tuple。容器是一種特殊用途的對(duì)象,可用于存儲(chǔ)不同的對(duì)象。它提供了一種訪問(wèn)所包含對(duì)象并遍歷它們的方法。
Python提供了實(shí)現(xiàn)容器數(shù)據(jù)類(lèi)型的collections模塊。在章節(jié)系列中,我們將學(xué)習(xí)集合模塊中的不同類(lèi)型集合融洽,其中包括:
- ChainMap
- Counter
- Deque
- DefaultDict
- NamedTuple
- OrderedDict
- UserDict
- UserList
- UserString
下面就來(lái)分別介紹這些容器類(lèi)型——鏈?zhǔn)接成洌–hainMap)。
認(rèn)識(shí)ChainMap
Python的所提供的ChainMap類(lèi)(就稱(chēng)為鏈映射類(lèi)),是個(gè)類(lèi)似字典(dict)的類(lèi),用于快速鏈接許多個(gè)映射,以便將它們作為單個(gè)單元處理。它通常比創(chuàng)建一個(gè)新字典并運(yùn)行多個(gè)update()調(diào)用要快得多。
其語(yǔ)法格式如下:
xchainMap = collections.ChainMap(*maps)
說(shuō)明:語(yǔ)法格式中的collections是導(dǎo)入的完成模塊名稱(chēng)。如果這樣導(dǎo)入該模塊:import collections as cts,則語(yǔ)法可變?yōu)椋篶lass cts.ChainMap(*maps),或則模糊導(dǎo)入:from collections import ChainMap,這樣可以修改為:ChainMap(*maps)。
ChainMap可將多個(gè)字典或其他映射組合在一起,創(chuàng)建一個(gè)單一的、可更新的視圖(字典列表)。如果沒(méi)有指定映射,則提供一個(gè)空字典,以便新的鏈?zhǔn)接成洌–hainMap)總是至少有一個(gè)映射可以。
鏈映射的底層映射存儲(chǔ)在一個(gè)列表中。該列表是公共的,可以使用maps屬性來(lái)訪問(wèn)或更新。除了maps屬性,鏈映射沒(méi)有其他的新擴(kuò)展?fàn)顟B(tài)。
ChainMap是通過(guò)引用來(lái)合并底層映射的。因此,如果其中一個(gè)底層映射得到更新,這些更改也將反映在ChainMap中。
鏈映射支持所有常用的字典(dict)方法。此外,還有一個(gè)maps屬性,用于創(chuàng)建新子上下文的方法,并且除了第一個(gè)映射,屬性maps可用于訪問(wèn)所有映射——maps是個(gè)列表。
對(duì)應(yīng)一個(gè)用戶(hù)可更新的映射列表,該列表從第一次搜索到最后一次搜索是有序的。它是唯一存儲(chǔ)的狀態(tài),可以通過(guò)修改來(lái)更改要搜索的映射。這樣的列表應(yīng)該始終至少包含一個(gè)映射。
來(lái)看下面的簡(jiǎn)單示例,代碼清單如下:
運(yùn)行程序輸出結(jié)果如下:
上述清單中,我們用兩個(gè)字典定義一個(gè)ChainMap對(duì)象(chain_map)。然后我們打印輸出ChainMap對(duì)象和maps屬性。正如在輸出中看到的,結(jié)果是這些字典的構(gòu)成視圖。
訪問(wèn)ChainMap的鍵值
我們可以通過(guò)使用keys()和values()方法來(lái)訪問(wèn)ChainMap的鍵和值。代碼示例如下:
上述代碼輸出結(jié)果為:
如程序輸出結(jié)果所示,chain_map.keys()的結(jié)果是一個(gè)KeysView(鍵視圖),chain_map.values()的結(jié)果是一個(gè)ValuesView(值視圖)。這兩個(gè)視圖類(lèi)型內(nèi)置類(lèi),都是可迭代對(duì)象,可以分別遍歷相應(yīng)的鍵名和值對(duì)象。例如:
輸出結(jié)果為:
結(jié)合代碼和輸出結(jié)果,很容易理解,即鏈?zhǔn)接成渚褪前讯鄠€(gè)映射(map有很多實(shí)現(xiàn),字典是其中的一種)打包成一個(gè)映射即鏈?zhǔn)接成洌缓罂梢韵癫僮髯值錁硬僮髟L問(wèn)。比如像字典一樣這樣來(lái)訪問(wèn)某個(gè)鍵的值:
也就是通過(guò)使用鍵名:chain_map[' one ']來(lái)訪問(wèn)ChainMap底層字典中單個(gè)項(xiàng)的值。
為ChainMap添加新映射
ChainMap可以包含任意數(shù)量的字典。我們使用內(nèi)置的new_child()方法向ChainMap添加新字典。new_child()方法返回一個(gè)新的ChainMap,其中包含著新映射,后跟當(dāng)前實(shí)例中的所有映射。這里需要注意的一點(diǎn)是,新添加的字典將放在ChainMap的開(kāi)頭。來(lái)看示例:
運(yùn)行程序,輸入結(jié)果如下:
這里需要注意的是,用鏈?zhǔn)接成涞膎ew_child()方法添加新字典后,不改變?cè)瓉?lái)的鏈映射,會(huì)返回一個(gè)新的ChainMap對(duì)象。另外,如果你修改鏈?zhǔn)接成渌挠成浠蜃值洌兓矊Ⅲw現(xiàn)在鏈?zhǔn)接成鋵?duì)象中。
另外,實(shí)踐中要當(dāng)心:如果你按照字典操作來(lái)添加新的鍵值對(duì),則該鍵值對(duì)會(huì)添加到鏈?zhǔn)接成渌牡谝粋€(gè)映射中,如:new_chain_map['X'] = 'Unkown' 。自己動(dòng)手試試看。
所含映射有相同鍵怎么辦?
底層上,鏈?zhǔn)接成渲饕菫榘讯鄠€(gè)字典或映射打包成一個(gè)映射,以便集中操作。如果所辦函的字典中有相同的鍵會(huì)怎樣呢?來(lái)看示例:
運(yùn)行程序輸出結(jié)果如下:
很顯然,鏈接的映射中出現(xiàn)相同字典項(xiàng)時(shí),只讀取第一個(gè),以第一個(gè)為準(zhǔn),而且當(dāng)你更新一個(gè)鍵的值時(shí),它也只是更新第一個(gè)映射內(nèi)容的鍵值。
如果你想一次更新所有映射中的相同鍵的值怎么辦呢?你可以自定義一個(gè)ChainMap子類(lèi)來(lái)實(shí)現(xiàn),或定義更新方法。因?yàn)镃hainMap中有個(gè)屬性maps持有完整的各個(gè)映射,可以基于此屬性來(lái)完成相同鍵的一次性更新。這里簡(jiǎn)單給個(gè)通過(guò)方法的方式實(shí)現(xiàn)多映射相同鍵的一次更新。示例代碼如下:
當(dāng)然,你可以寫(xiě)得更復(fù)雜一點(diǎn),以完成更多的需要,也可實(shí)現(xiàn)一次多個(gè)映射中的相同鍵的值。自己動(dòng)手試試吧。
本文小結(jié)
本文主要介紹了Python集合模塊中的鏈?zhǔn)接成淙萜鳌狢hainMap的使用,可以把多個(gè)字典打包成一個(gè)對(duì)象來(lái)操作。同時(shí)需要注意的是,該映射只是對(duì)原字典的引用,當(dāng)你修改原字典時(shí),相應(yīng)的變化也為體現(xiàn)在鏈?zhǔn)接成渲小M瑫r(shí),在為ChainMap新增新的鍵值對(duì)時(shí),它會(huì)添加到所包含的第一個(gè)映射對(duì)象中。






