1 collections 模塊
python 為我們提供了四種基本的容器數(shù)據(jù)類(lèi)型 list,tuple,dict,set。在大部分處理集合類(lèi)型數(shù)據(jù)的應(yīng)用場(chǎng)景,這四種數(shù)據(jù)結(jié)構(gòu)都能輕松勝任。但是在處理大量數(shù)據(jù)和處理復(fù)雜數(shù)據(jù)元素運(yùn)算的時(shí)候,這四中數(shù)據(jù)結(jié)構(gòu)明顯功能單一,且運(yùn)算效率較低。python標(biāo)準(zhǔn)庫(kù)為我們提供了collections包,里面提供很多功能強(qiáng)大的容器類(lèi)型,熟練掌握這些容器類(lèi)型,有助于提高我們的代碼質(zhì)量。這里主要介紹如下幾種數(shù)據(jù)結(jié)構(gòu)。
- namedtuple
- OrderedDict
- defaultdict
2 namedtuple
2.1簡(jiǎn)介
namedtuple是一個(gè)函數(shù),創(chuàng)建一個(gè)自定義的tuple對(duì)象,規(guī)定tuple元素個(gè)數(shù)以及其對(duì)應(yīng)的屬性,可以根據(jù)屬性而不是索引來(lái)訪問(wèn),具有tuple的不變性,又可以根據(jù)屬性來(lái)引用。創(chuàng)建的namedtuple是tuple類(lèi)型的子類(lèi)。
In [2]: from collections import namedtuple
In [3]: Point = namedtuple('Ponit',['x','y'])
In [4]: p = Point(1,2)
In [5]: p.x
Out[5]: 1
In [6]: p.y
Out[6]: 2
In [7]: type(p)
Out[7]: __main__.Ponit
In [8]: isinstance(p,tuple)
Out[8]: True
In [9]: p.x=5
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-9-c7ca42e996c7> in <module>()
----> 1 p.x=5
AttributeError: can't set attribute
2.2 自帶描述信息
- 單純的看一個(gè)元組的信息,我們很難看出元組以及元組每一項(xiàng)所表示的含義,采用namedtuple后,相當(dāng)于給元組增加了文檔描述。
- namedtuple實(shí)例沒(méi)有對(duì)象字典,是一個(gè)輕量級(jí)數(shù)據(jù)結(jié)構(gòu),與普通元組相比并不需要更多內(nèi)存。這使得他們比字典更快。
下面代碼清楚的描述了一個(gè)圓的信息,circle相比較于circle2就要清楚太多了。
In [11]: Circle = namedtuple('Circle',['point','r'])
In [12]: circle = Circle(p,'5')
In [13]: circle
Out[13]: Circle(point=Ponit(x=1, y=2), r='5')
In [14]: circle.point.x
Out[14]: 1
In [15]: circle.point.y
Out[15]: 2
In [16]: circle.r
Out[16]: '5'
In [17]: circle2 = ((1,2),5)
In [18]: circle2
Out[18]: ((1, 2), 5)
2.3 實(shí)用方法
namedtuple是tuple的子類(lèi),具有tuple的所有方法
In [23]: p1 = Point(2,3)
In [24]: p2 = Point(3,4)
In [25]: p1+p2
Out[25]: (2, 3, 3, 4)
In [26]: p1.index(0)
In [27]: p1.index(2)
Out[27]: 0
In [29]: p1.count(1)
Out[29]: 0
In [30]: len(p1)
Out[30]: 2
namedtuple提供了其他方法讓我么更靈活的使用該數(shù)據(jù)結(jié)構(gòu)
In [46]: p._asdict()
Out[46]: OrderedDict([('x', 1), ('y', 2)])
In [47]: p._fields
Out[47]: ('x', 'y')
In [49]: p._make([1,2]) #傳入可迭代類(lèi)型
Out[49]: Ponit(x=1, y=2)
In [51]: p._replace(x=1,y=3) # 傳入**kwds
Out[51]: Ponit(x=1, y=3)
3 OrderedDict
3.1 簡(jiǎn)介
python 中的dict是無(wú)序的,在對(duì)dict做迭代時(shí)我們無(wú)法確定dict的順序。
OrderedDict是dict的子類(lèi),支持一般的dict方法,它會(huì)記錄key加入的順序,從而實(shí)現(xiàn)有序字典,這種數(shù)據(jù)結(jié)構(gòu)具有強(qiáng)大的威力。
In [65]: d = dict([('a',1),('b',2),('c',3)])
In [66]: d
Out[66]: {'a': 1, 'b': 2, 'c': 3}
In [67]: od = OrderedDict([('a',1),('b',2),('c',3)])
In [68]: od
Out[68]: OrderedDict([('a', 1), ('b', 2), ('c', 3)])
In [70]: od = OrderedDict()
In [71]: od['z']=1
In [72]: od['x']=2
In [73]: od['y']=3
In [74]: od
Out[74]: OrderedDict([('z', 1), ('x', 2), ('y', 3)])
In [75]: for i in od:
...: print(i)
...:
z
x
y
OrderedDict會(huì)按照其插入的順序給予鍵值對(duì)以固定的順序,這樣就可以得到“穩(wěn)定”的迭代對(duì)象,并且可以取出固定位置的鍵值對(duì)
In [88]: od
Out[88]: OrderedDict([('z', 1), ('x', 2), ('y', 3)])
In [89]: od.get([x for x in od][2])
Out[89]: 3
3.2根據(jù)字典的鍵或值的特征進(jìn)行排序
實(shí)現(xiàn)靈活排序
In [90]: d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
In [91]: OrderedDict(sorted(d.items(), key=lambda t: t[0])) # 按照鍵排序
Out[91]: OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
In [92]: OrderedDict(sorted(d.items(), key=lambda t: t[1])) # 按照值排序
Out[92]: OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
In [93]: OrderedDict(sorted(d.items(), key=lambda t: len(t[0]))) # 按照鍵長(zhǎng)度排序
Out[93]: OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
# tips: sorted函數(shù)key變量,是指在對(duì)可迭代對(duì)象排序的時(shí)候,按照可迭代對(duì)象的什么特征進(jìn)行排序
In [101]: a = ['5','40','345','6000']
In [102]: sorted(a #字符串第一個(gè)字符
Out[102]: ['345', '40', '5', '6000']
In [103]: sorted(a,key=lambda t:int(t)) #字符竄轉(zhuǎn)化為int型之后
Out[103]: ['5', '40', '345', '6000']
這樣就實(shí)現(xiàn)了對(duì)字典元素的順序的定義
3.3 OrderedDict 相關(guān)方法
根據(jù)可迭代對(duì)象生成值為None 的有序字典
In [109]: d = OrderedDict.fromkeys('abcde')
In [110]: d
Out[110]: OrderedDict([('a', None), ('b', None), ('c', None), ('d', None), ('e', None)])
In [9]: d.move_to_end('b')
In [10]: d
Out[10]: OrderedDict([('a', None), ('c', None), ('d', None), ('e', None), ('b', None)])
In [11]: d.popitem()
Out[11]: ('b', None)
In [12]: d.popitem()
Out[12]: ('e', None)
In [13]: d
Out[13]: OrderedDict([('a', None), ('c', None), ('d', None)])
4 defaultdict
4.1 簡(jiǎn)介
默認(rèn)值字典
python的dict數(shù)據(jù)類(lèi)型在取值dict[key]的時(shí)候如果沒(méi)有key會(huì)報(bào)錯(cuò),defaultdict通過(guò)則避免了這一行為.使用defaultdict,只要你傳入一個(gè)默認(rèn)的工廠方法,那么請(qǐng)求一個(gè)不存在的key時(shí), 便會(huì)調(diào)用這個(gè)工廠方法使用其結(jié)果來(lái)作為這個(gè)key的默認(rèn)值。
其原理是在dict基礎(chǔ)上實(shí)現(xiàn)了_missing_會(huì)調(diào)用傳入的工廠方法 當(dāng)_getitem_不存在的時(shí)候,就會(huì)觸發(fā),給本來(lái)不存在的鍵賦默認(rèn)值
工廠方法默認(rèn)為None,這個(gè)時(shí)候由于缺少工廠方法,對(duì)不存在的建設(shè)置默認(rèn)值就不會(huì)生效
In [53]: d = defaultdict()
In [54]: d
Out[54]: defaultdict(None, {})
In [55]: d['a']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-55-4ff0d9af6f7a> in <module>()
----> 1 d['a']
KeyError: 'a'
當(dāng)傳入工廠方法的時(shí)候,設(shè)置默認(rèn)值就會(huì)生效.
In [56]: d = defaultdict(list)
In [57]: d['a']
Out[57]: []
In [58]: d
Out[58]: defaultdict(list, {'a': []})
In [59]: d.get('a')
Out[59]: []
In [60]: d['a']
Out[60]: []
4.2 實(shí)現(xiàn)序列元素的收集
可以利用defaultdict實(shí)現(xiàn)序列元素的分類(lèi)收集
In [34]: members = [
...: # Age, name
...: ['male', 'John'],
...: ['male', 'Jack'],
...: ['female', 'Lily'],
...: ['male', 'Pony'],
...: ['female', 'Lucy'],
...: ]
In [35]: result = defaultdict(list)
...: for sex, name in members:
...: result[sex].append(name)
...:
In [36]: result
Out[36]: defaultdict(list,{'female': ['Lily', 'Lucy'], 'male'['John', 'Jack', 'Pony']}
In [37]: result['male']
Out[37]: ['John', 'Jack', 'Pony']
當(dāng)不存在key時(shí)候就會(huì)自動(dòng)調(diào)用list工廠函數(shù),產(chǎn)生一個(gè)空的列表,
上面的代碼片段就實(shí)現(xiàn)了對(duì)具有相同信息的序列結(jié)構(gòu)的篩選.使用dict可用如下方式實(shí)現(xiàn).
In [39]: d = {}
In [40]: for sex, name in members:
...: d.setdefault(sex,[]).append(name)
...:
In [41]: d
Out[41]: {'female': ['Lily', 'Lucy'], 'male': ['John', 'Jack', 'Pony']}
帶有默認(rèn)值的字典
In [49]: f = lambda :'chaoge'
In [50]: d = defaultdict(f)
In [51]: d['a']
Out[51]: 'chaoge'
In [52]: d
Out[52]: defaultdict(<function __main__.<lambda>>, {'a': 'chaoge'})