python字典和集合
構造方法與字典推導式
>>> a = dict(one=1, two=2, three=3) #法一 >>> b = {‘one‘: 1, ‘two‘: 2, ‘three‘: 3} #法二 >>> c = dict(zip([‘one‘, ‘two‘, ‘three‘], [1, 2, 3])) #法三 >>> d = dict([(‘two‘, 2), (‘one‘, 1), (‘three‘, 3)]) #法四 >>> e = dict({‘three‘: 3, ‘one‘: 1, ‘two‘: 2}) #法五 >>> a == b == c == d == e True
DIAL_CODES = [ #承載成對數據的列表,用於字典推導 (86, ‘China‘), (91, ‘india‘), (1, ‘United States‘), (7, ‘Russia‘), (81, ‘Japan‘), ] country_code = {country: code for code, country in DIAL_CODES} #字典推導式,類似於列表推導式 print(country_code) new_country_code = {code: country.upper() for country, code in country_code.items() if code > 80} #篩選code值大於60的並將country改為大寫 print(new_country_code) #結果 {‘United States‘: 1, ‘Japan‘: 81, ‘Russia‘: 7, ‘india‘: 91, ‘China‘: 86} {81: ‘JAPAN‘, 91: ‘INDIA‘, 86: ‘CHINA‘}
dict常見方法(collections庫中的defaultdict,Orderedict同樣有這些方法)
1 dict.clear() //刪除字典內所有元素
2 dict.copy() //返回一個字典的淺復制
3 dict.fromkeys(seq[, val]) //創建一個新字典,以序列 seq 中元素做字典的鍵,val 為字典所有鍵對應的初始值
4 dict.get(key, default=None) //返回指定鍵的值,如果值不在字典中返回default值
5 dict.has_key(key) //如果鍵在字典dict裏返回true,否則返回false (可用key in dict代替)
6 dict.items()
7 dict.keys() //以列表返回一個字典所有的鍵
8 dict.setdefault(key, default=None) //和get()類似, 但如果鍵不存在於字典中,將會添加鍵並將值設為default
9 dict.update(dict2) //把字典dict2的鍵/值對更新到dict裏
10 dict.values() //以列表返回字典中的所有值以列表返回字典中的所有值
11 pop(key[,default]) //刪除字典給定鍵 key 所對應的值,返回值為被刪除的值。key值必須給出。 否則,返回default值。
12 popitem() //隨機返回並刪除字典中的一對鍵和值。
找不到鍵時的選擇
1.當字典d[k]不能找到正確的鍵的時候,會拋出keyError異常。上述方法中的dict.get(key, default=None)和dict.setdefault(key, default=None)均可解決問題。
而需要正確區分兩個函數的合適場合,當需要更新某個鍵對應的值時,使用setdefault這個函數則更為合適,因為get函數只是返回default值,並不對字典進行更新。
2.使用collections中.defaultdict創建字典而不是dict
實例化defaultdict時,需要給構造方法提供一個可調用對象,這個可調用對象會在__getitem__碰到找不到的鍵的時候被調用,讓__getitem__返回某個默認值。
以list為例,新建字典d = defaultdict(list),如果new_key在字典中不存在,則d[new_key]會按照以下步驟:
1)調用list來新建一個列表
2)把這個列表作為值,‘new_key’作為鍵,放到d中
3)返回列表引用。
其他映射類型
collections.OrderedDict //特點:添加鍵時保持順序。popitem()方法刪除的是最後一個元素,類似棧;而可用popitem(last=False)來刪除第一個元素,類似隊列。
collections.ChainMap //特點:可以容納多個不同的映射對象,查找時,這些對象會被當做一個整體逐一查找,直到鍵被找到。
collections.Counter //特點:為鍵(key)維護一個計數器,每次更新一個鍵時會增加這個計數器。實現了+和-運算來合並記錄。most_commot([n])方法,按照次序返回映射裏面最常見的n個鍵和他們的計數。下例:
from collections import Counter ct = Counter(‘trueorfalse‘) print(ct) ct.update(‘tree‘) #更新 print(ct) print(ct.most_common(3)) #獲取最多的三個鍵 new_ct = Counter(‘tree‘) print(ct + new_ct) #加號 print(ct - new_ct) #減號 Counter({‘r‘: 2, ‘e‘: 2, ‘u‘: 1, ‘o‘: 1, ‘a‘: 1, ‘t‘: 1, ‘s‘: 1, ‘l‘: 1, ‘f‘: 1}) Counter({‘e‘: 4, ‘r‘: 3, ‘t‘: 2, ‘u‘: 1, ‘o‘: 1, ‘a‘: 1, ‘s‘: 1, ‘l‘: 1, ‘f‘: 1}) [(‘e‘, 4), (‘r‘, 3), (‘t‘, 2)] Counter({‘e‘: 6, ‘r‘: 4, ‘t‘: 3, ‘u‘: 1, ‘o‘: 1, ‘a‘: 1, ‘f‘: 1, ‘l‘: 1, ‘s‘: 1}) Counter({‘r‘: 2, ‘e‘: 2, ‘u‘: 1, ‘o‘: 1, ‘a‘: 1, ‘t‘: 1, ‘f‘: 1, ‘l‘: 1, ‘s‘: 1})
自定義類型 UserDict
UserDict不是dict的子類,但UserDict有一個data屬性,是dict的實例,data是UserDict最終存儲數據的地方。
UserDict繼承的是MutableMapping,MutableMapping繼承的是Mapping。
MutableMapping.update不但可直接使用,而且用在__init__中,讓構造方法可以利用各種參數(其他映射類型,可叠代的(key,value)元組對)來新建事例。
Mapping.get方法在鍵不存在時,將鍵轉化為字符串查詢。
不可變映射類型 types.MappingProxyType //返回一個動態視圖
from types import MappingProxyType d = {1: ‘A‘} d_proxy = MappingProxyType(d) print(d_proxy) {1: ‘A‘} d_proxy[2] = ‘x‘ #不可變,拋出異常 Traceback (most recent call last): File "<input>", line 1, in <module> TypeError: ‘mappingproxy‘ object does not support item assignment d[2] = ‘x‘ print(d_proxy) #動態變化 mappingproxy({1: ‘A‘, 2: ‘x‘})
集合 (set和frozenset)
set本身元素必須是可散列的,但frozenset可以。
構造方法
s = {1,2,3} //速度快 s = set{[1,2,3]} //常用 s = frozenset([1, 2, 3, 4, 5, 4]) s = {i for i in range(5)} //集合推導式
一個陷阱:{ }構造的是一個字典而非集合,需用set()方法。
集合數學運算符(集合s和集合z,,以下方法會修改s)
交集 s & z s &= z
並集 s | z s |= z
差集 s \ z s \= z
對稱差集 s ^ z s ^= z
集合比較運算符(集合s和集合z,返回布爾值)
屬於 e in s
子集 s <= z
真子集 s < z
父集 s >= z
真父集 s > z
其他常用方法
add(e) //向集合中添加元素e
clear() //清空集合
copy() //返回集合的淺拷貝
pop() //刪除並返回任意的集合元素(如果集合為空,會引發 KeyError)
remove(e) //刪除集合中的e元素(如果元素不存在,會引發 KeyError)
內置方法
all() //如果集合中的所有元素都是 True(或者集合為空),則返回 True。
any() //如果集合中的所有元素都是 True,則返回 True;如果集合為空,則返回 False。
enumerate() //返回一個枚舉對象,其中包含了集合中所有元素的索引和值(配對)。
len() //返回集合的長度(元素個數)
max() //返回集合中的最大項
min() //返回集合中的最小項
sorted() //從集合中的元素返回新的排序列表(不排序集合本身)
sum() //返回集合的所有元素之和
字典實現方式(散列表)
4個問題
【1】字典和集合的效率?
【2】字典為什麽是無序的?
【3】所有對象均可作為python中的鍵?
【4】為什麽不能在叠代時往dict或set中添加元素。
散列表是一個稀疏數組(含有大量空白元素的數組),散列表單元稱為表元。dict的散列表中,每個鍵值對占用一個表元,分為鍵的引用和值的引用兩部分。表元大小一致,故通過偏移量來讀取某個單元。python會設法保證大概有1/3的空白表元【1】,當達到這個閾值時,散列表會被復制到一個新的更大的空間中【2】【4】。(復制時會使用散列表算法)
散列性和相等性:字典必須保證鍵是可散列的【3】(在生命周期中,散列值是不變的對象);另外如果兩個散列對象相等,那麽他們的散列值相等,例如1和1.0。
散列表算法:獲取d[k]的值時,會調用hash(k)來計算k的散列值,把這個值最低幾位數字當做偏移量【5】,在散列表中查找表元,若表元為空,會拋出keyError異常;若不是空的,則產生散列沖突,算法會在散列值中另取幾位,用特殊方法處理後,得到新的偏移量來查找表元。->反復如上步驟,直到產生keyError異常或查找到匹配的鍵。
上述特性分別決定了:
【1】字典在內存中開銷巨大
【2】字典是可能是亂序的;【4】無論何時添加新的鍵都有可能讓字典產生擴容,而這個過程會發生新的散列沖突,導致新散列表的鍵次序變化;而在叠代時修改字典可能會跳過一些鍵或叠代字典中已有的鍵。
【3】鍵必須是可散列的
【5】鍵查詢很快
python字典和集合