1. 程式人生 > >python字典和集合

python字典和集合

字符串 tree 查找 get方法 空白 mon 自定義類 字典實現 例如

構造方法與字典推導式

>>> 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字典和集合