摘要:小總結(jié)標(biāo)準(zhǔn)庫(kù)里的所有映射類型都是利用來實(shí)現(xiàn)只有可散列的數(shù)據(jù)類型才能用作這些映射里的鍵值不用字典推導(dǎo)用處理找不到的鍵找不到鍵返回某種默認(rèn)值底層是與調(diào)用實(shí)現(xiàn)的字典插入更新原理其他大多數(shù)映射類型都提供了兩個(gè)很強(qiáng)大的方法和。
字典和集合
標(biāo)準(zhǔn)庫(kù)里的所有映射類型都是利用 dict 來實(shí)現(xiàn)的
只有可散列的數(shù)據(jù)類型才能用作這些映射里的鍵(值不用)
一個(gè)對(duì)象是可散列的
它的散列值是不變的
對(duì)象需要實(shí)現(xiàn) __hash__() 方法
可散列對(duì)象還要有 __qe__() 方法
字典推導(dǎo)DIAL_CODES = [(86, "China"), (91, "India"), (1, "United States"), (62, "Indonesia") ] country_code = {country: code for code, country in DIAL_CODES }
結(jié)果常見的映射方法 page137 用setdefault處理找不到的鍵
{"China": 86, "India": 91, "United States": 1, "Indonesia": 62}
##找對(duì)應(yīng)的key,沒有的話返回默認(rèn)值 my_dict = {"name":"longe","age":8} my_dict.setdefault("namerrr","default") print(my_dict)
用 setdefault 只需要一次就可以完成整個(gè)操作。
defaultdict找不到鍵返回某種默認(rèn)值在實(shí)例化一個(gè) defaultdict 的時(shí)候
這個(gè)可調(diào)用對(duì)象會(huì)在 getitem 碰到找不到的鍵的時(shí)候被調(diào)用,
讓 getitem 返回某種默認(rèn)值。
實(shí)現(xiàn)方式defaultdict 里的 default_factory 只會(huì)在__getitem__ 里被調(diào)用
dd[k] 這個(gè)表達(dá)式會(huì)調(diào)用 default_factory 創(chuàng)造某個(gè)默認(rèn)值,
dd.get(k) 則會(huì)返回 None。
原理__missing__這個(gè)方法
所有這一切背后的功臣其實(shí)是特殊方法 __missing__。
它會(huì)在defaultdict 遇到找不到的鍵的時(shí)候調(diào)用 default_factory
自定義一個(gè)映射類型,更合適的策略其實(shí)是繼承collections.UserDict 類
只是為了演示 missing 是如何被dict.__getitem__ 調(diào)用的。
class StrKeyDict0(dict): def __missing__(self, key): if isinstance(key, str): raise KeyError(key) return self[str(key)] def get(self, key, default=None): try: return self[key] except KeyError: return default def __contains__(self, key): return key in self.keys() or str(key) in self.keys()
isinstance(key, str) 測(cè)試在上面的__missing__ 中是必需的
但是如果 str(k) 不是一個(gè)存在的鍵,代碼就會(huì)陷入無限遞歸。
這是因?yàn)?missing 的最后一行中的 self[str(key)] 會(huì)調(diào)用 __getitem__,
而這個(gè) str(key) 又不存在,于是 __missing__又會(huì)被調(diào)用。
精簡(jiǎn)版本
import collections class StrKeyDict(collections.UserDict): def __missing__(self, key): if isinstance(key, str): raise KeyError(key) return self[str(key)] def __contains__(self, key): return str(key) in self.data def __setitem__(self, key, item): self.data[str(key)] = item
setitem 會(huì)把所有的鍵都轉(zhuǎn)換成字符串。由于把具體的實(shí)現(xiàn)委字典的變種
托給了 self.data 屬性,這個(gè)方法寫起來也不難
這個(gè)類型在添加鍵的時(shí)候會(huì)保持順序,因此鍵的迭代次序總是一致
的。
該類型可以容納數(shù)個(gè)不同的映射對(duì)象,然后在進(jìn)行鍵查找操作的時(shí)
候,這些對(duì)象會(huì)被當(dāng)作一個(gè)整體被逐個(gè)查找,直到鍵被找到為止。
這個(gè)映射類型會(huì)給鍵準(zhǔn)備一個(gè)整數(shù)計(jì)數(shù)器。每次更新一個(gè)鍵的時(shí)候
都會(huì)增加這個(gè)計(jì)數(shù)器。
這個(gè)類其實(shí)就是把標(biāo)準(zhǔn) dict 用純 Python 又實(shí)現(xiàn)了一遍。
跟 OrderedDict、ChainMap 和 Counter 這些開箱即用的類型不
同,UserDict 是讓用戶繼承寫子類的。下面就來試試。
from unicodedata import name aa = {chr(i) for i in range(32, 256) if "SIGN" in name(chr(i), "")} print(aa)集合的數(shù)學(xué)運(yùn)算 page161 字典空間
因?yàn)?Python 會(huì)設(shè)法保證大概還有三分之一的表元是空的,所以在快要達(dá)
到這個(gè)閾值的時(shí)候,原有的散列表會(huì)被復(fù)制到一個(gè)更大的空間里面。
散列表原理為了獲取 my_dict[search_key] 背后的值
Python 首先會(huì)調(diào)用hash(search_key) 來計(jì)算 search_key 的散列值,
把這個(gè)值最低的幾位數(shù)字當(dāng)作偏移量
在散列表里查找表元(具體取幾位,得看當(dāng)前散列表的大小
若找到的表元是空的,則拋出 KeyError 異常。
若不是空的,則表元里會(huì)有一對(duì) found_key:found_value。
這時(shí)候 Python 會(huì)檢驗(yàn) search_key == found_key 是否為真,如 果它們相等的話,就會(huì)返回found_value。
如果 search_key 和 found_key 不匹配的話,這種情況稱為散列 沖突。
原理圖 添加新元素和更新現(xiàn)有鍵值添加新元素和更新現(xiàn)有鍵值的操作幾乎跟上面一樣。
只不過對(duì)于前者,在發(fā)現(xiàn)空表元的時(shí)候會(huì)放入一個(gè)新元素;
對(duì)于后者,在找到相對(duì)應(yīng)的表元后,原表里的值對(duì)象會(huì)被替換成新值。
字典浪費(fèi)存儲(chǔ)空間(不過沒有幾百萬對(duì)象,內(nèi)存好幾個(gè)G不用考慮)
dict 的實(shí)現(xiàn)是典型的空間換時(shí)間:字典類型有著巨大的內(nèi)存開銷
當(dāng)往 dict 里添加新鍵而又發(fā)生散列沖突的時(shí)候,新鍵可能會(huì)被安
排存放到另一個(gè)位置。
無論何時(shí)往字典里添加新的鍵,Python 解釋器都可能做出為字典擴(kuò)
容的決定。
擴(kuò)容導(dǎo)致的結(jié)果就是要新建一個(gè)更大的散列表,并把字典里已有的元素添加到新表里。
這個(gè)過程中可能會(huì)發(fā)生新的散列沖突,導(dǎo)致新散列表中鍵的次序變化。
要注意的是,上面提到的這些變化是否會(huì)發(fā)生以及如何發(fā)生,都依賴于字典背后的具體實(shí)現(xiàn),
因此你不能很自信地說自己知道背后發(fā)生了什么。
如果你在迭代一個(gè)字典的所有鍵的過程中同時(shí)對(duì)字典進(jìn)行修改,那么這個(gè)循環(huán)很有可
能會(huì)跳過一些鍵——甚至是跳過那些字典中已經(jīng)有的鍵。
更新字典的主要使用姿勢(shì)由此可知,不要對(duì)字典同時(shí)進(jìn)行迭代和修改。
如果想掃描并修改一個(gè)字典,最好分成兩步來進(jìn)行:
首先對(duì)字典迭代,以得出需要添加的內(nèi)容,把這些內(nèi)容放在一個(gè)新字典里;
迭代結(jié)束之后再對(duì)原有字典進(jìn)行更新。
小總結(jié):標(biāo)準(zhǔn)庫(kù)里的所有映射類型都是利用 dict 來實(shí)現(xiàn)
只有可散列的數(shù)據(jù)類型才能用作這些映射里的鍵(值不用)
字典推導(dǎo)
用setdefault處理找不到的鍵
defaultdict找不到鍵返回某種默認(rèn)值
底層是 getitem 與__miss__調(diào)用實(shí)現(xiàn)的
字典插入更新原理!!!
其他大多數(shù)映射類型都提供了兩個(gè)很強(qiáng)大的方法:setdefault 和
update。
setdefault 方法可以用來更新字典里存放的可變值(比如列
表),從而避免了重復(fù)的鍵搜索。
update 方法則讓批量更新成為可能,它可以用來插入新值或者更新已有鍵值對(duì),它的參數(shù)可以是包含(key, value) 這種鍵值對(duì)的可迭代對(duì)象,或者關(guān)鍵字參數(shù)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/41625.html
摘要:第一章數(shù)據(jù)類型隱式方法利用快速生成字典方法方法通過下標(biāo)找元素自動(dòng)支持切片操作可迭代方法與如果是一個(gè)自定義類的對(duì)象,那么會(huì)自己去調(diào)用其中由你實(shí)現(xiàn)的方法。若返回,則會(huì)返回否則返回。一個(gè)對(duì)象沒有函數(shù),解釋器會(huì)用作為替代。 第一章 python數(shù)據(jù)類型 1 隱式方法 利用collections.namedtuple 快速生成字典 import collections Card = coll...
摘要:第一章數(shù)據(jù)類型隱式方法利用快速生成類方法方法通過下標(biāo)找元素自動(dòng)支持切片操作可迭代方法與如果是一個(gè)自定義類的對(duì)象,那么會(huì)自己去調(diào)用其中由你實(shí)現(xiàn)的方法。若返回,則會(huì)返回否則返回。一個(gè)對(duì)象沒有函數(shù),解釋器會(huì)用作為替代。 第一章 python數(shù)據(jù)類型 1 隱式方法 利用collections.namedtuple 快速生成類 import collections Card = collec...
摘要:可以通過定位參數(shù)和關(guān)鍵字參數(shù)傳入的形參多數(shù)函數(shù)的參數(shù)屬于此類。就像數(shù)據(jù)格式化一樣數(shù)據(jù)帶上標(biāo)簽自行創(chuàng)建函數(shù)它會(huì)自行創(chuàng)建函數(shù)。創(chuàng)建的函數(shù)會(huì)在對(duì)象上調(diào)用參數(shù)指定的方法自己創(chuàng)建函數(shù)凍結(jié)參數(shù)這個(gè)高階函數(shù)用于部分應(yīng)用一個(gè)函數(shù)。 高階函數(shù) 接受函數(shù)為參數(shù),或者把函數(shù)作為結(jié)果返回的函數(shù)是高階函數(shù) def reverse(word): return word[::-1] ...
摘要:把具名元組以的形式返回,我們可以利用它來把元組里的信息友好地呈現(xiàn)出來。數(shù)組支持所有跟可變序列有關(guān)的操作,包括和。雙向隊(duì)列和其他形式的隊(duì)列類雙向隊(duì)列是一個(gè)線程安全可以快速?gòu)膬啥颂砑踊蛘邉h除元素的數(shù)據(jù)類型。 列表表達(dá)式 >>> symbols = $¢£¥€¤ >>> codes = [ord(symbol) for symbol in symbols] >>> codes [36, 16...
摘要:函數(shù)裝飾器和閉包嚴(yán)格來說,裝飾器只是語法糖。何時(shí)執(zhí)行裝飾器它們?cè)诒谎b飾的函數(shù)定義之后立即運(yùn)行。裝飾器突出了被裝飾的函數(shù)的作用,還便于臨時(shí)禁用某個(gè)促銷策略只需把裝飾器注釋掉。 函數(shù)裝飾器和閉包 嚴(yán)格來說,裝飾器只是語法糖。如前所示,裝飾器可以像常規(guī)的可調(diào)用對(duì)象那樣調(diào)用,其參數(shù)是另一個(gè)函數(shù)。有時(shí),這樣做更方便,尤其是做元編程(在運(yùn)行時(shí)改變程序的行為)時(shí)。 Python何時(shí)執(zhí)行裝飾器 它們?cè)?..
閱讀 3221·2023-04-26 02:27
閱讀 2950·2021-11-22 13:54
閱讀 1042·2021-11-12 10:36
閱讀 3918·2021-10-09 09:44
閱讀 3308·2021-10-09 09:41
閱讀 1437·2021-09-22 10:02
閱讀 3030·2019-08-30 15:56
閱讀 3233·2019-08-30 11:02