python進(jìn)階collections標(biāo)準(zhǔn)庫(kù)使用示例詳解
前言
這個(gè)模塊實(shí)現(xiàn)了特定目標(biāo)的容器,以提供Python標(biāo)準(zhǔn)內(nèi)建容器dict
,list
,set
, 和tuple
的替代選擇。
這個(gè)模塊提供了以下幾個(gè)函數(shù)
函數(shù) | 作用 |
---|---|
namedtuple() | 創(chuàng)建命名元組子類的工廠函數(shù) |
deque | 類似列表(list)的容器,實(shí)現(xiàn)了在兩端快速添加(append)和彈出(pop) |
ChainMap | 類似字典(dict)的容器類,將多個(gè)映射集合到一個(gè)視圖里面 |
Counter | 字典的子類,提供了可哈希對(duì)象的計(jì)數(shù)功能 |
OrderedDict | 字典的子類,保存了他們被添加的順序 |
defaultdict | 字典的子類,提供了一個(gè)工廠函數(shù),為字典查詢提供一個(gè)默認(rèn)值 |
UserDict | 封裝了字典對(duì)象,簡(jiǎn)化了字典子類化 |
UserList | 封裝了列表對(duì)象,簡(jiǎn)化了列表子類化 |
UserString | 封裝了字符串對(duì)象,簡(jiǎn)化了字符串子類化 |
namedtuple
namedtuple的由來(lái)
因?yàn)樵M的局限性:不能為元組內(nèi)部的數(shù)據(jù)進(jìn)行命名,所以往往我們并不知道一個(gè)元組所要表達(dá)的意義,所以引入namedtuple
這個(gè)工廠函數(shù),來(lái)構(gòu)造一個(gè)帶字段名的元組。namedtuple
繼承自tuple
類
命名元組賦予每個(gè)位置一個(gè)含義,提供可讀性。它們可以用于任何普通元組,并添加了通過(guò)名字獲取值的能力,通過(guò)索引值也是可以的。
namedtuple的格式
collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
typename
: 返回一個(gè)新的元組子類,名為typename。這個(gè)新的子類用于創(chuàng)建類元組的對(duì)象,可以通過(guò)字段名來(lái)獲取屬性值,同樣也可以通過(guò)索引和迭代獲取值。field_names
: 像['x', 'y'] 一樣的字符串序列。另外field_names
可以是一個(gè)純字符串,用空白或逗號(hào)分隔開(kāi)元素名,比如 'x y' 或者 'x, y' 。rename=False
: 如果rename為true,無(wú)效字段名會(huì)自動(dòng)轉(zhuǎn)換成_+索引值
,比如 ['abc', 'def', 'ghi', 'abc'] 轉(zhuǎn)換成 ['abc', '_1', 'ghi', '_3'] , 消除關(guān)鍵詞def和重復(fù)字段名abc。default=None
: defaults 可以為 None 或者是一個(gè)默認(rèn)值的 iterable 。default默認(rèn)值賦值跟我們平常的默認(rèn)值相反,default默認(rèn)值是從最右邊開(kāi)始,比如field_names
中提供了3個(gè)字段['x', 'y', 'z']
,default默認(rèn)值設(shè)置為(1, 2)
,那么我們必須為x指定1個(gè)值,y默認(rèn)值為1,z默認(rèn)值為2module=None
: 如果 module 值有定義,命名元組的module屬性值就被設(shè)置。
namedtuple聲明以及實(shí)例化
我們首先創(chuàng)建一個(gè)User類,定義3個(gè)字段name
、age
、height
,并給age設(shè)置默認(rèn)值為18,給height設(shè)置了默認(rèn)值180
User = namedtuple('User', ['name', 'age', 'height'], defaults=(18, 180)) print(User.__mro__)
我們查看結(jié)果
(<class '__main__.User'>, <class 'tuple'>, <class 'object'>)
可以看到我們聲明的User類是繼承于tuple
,接下來(lái)我們創(chuàng)建實(shí)例
user1 = User(name='jkc') user2 = User(name='jkc2', age=20, height=198) print(user1) print(user2) print(user1.name) print(user2.age)
運(yùn)行結(jié)果為
User(name='jkc', age=18, height=180)
User(name='jkc2', age=20, height=198)
jkc
20
namedtuple的方法和屬性
命名元組還支持三個(gè)額外的方法和兩個(gè)屬性。為了防止字段名沖突,方法和屬性以下劃線開(kāi)始。_make(iterable)
類方法從存在的序列或迭代實(shí)例創(chuàng)建一個(gè)新實(shí)例。
>>> t = ['jkc3', 25, 190] >>> User._make(t) User(name='jkc3', age=25, height=190)
_asdict()
返回一個(gè)新的 dict ,它將字段名稱映射到它們對(duì)應(yīng)的值
>>> user4 = User(name='jkc4', age=28, height=200) >>> user4._asdict() {'name': 'jkc4', 'age': 28, 'height': 200}
_replace(**kwargs)
返回一個(gè)新的命名元組實(shí)例,并將指定域替換為新的值
>>> user5 = User(name='jkc5', age=30, height=210) >>> user5._replace(age=18) User(name='jkc5', age=30, height=210)
_fields
字符串元組列出了字段名。用于提醒和從現(xiàn)有元組創(chuàng)建一個(gè)新的命名元組類型
>>> user5._fields ('name', 'age', 'height')
_field_defaults
字典將字段名稱映射到默認(rèn)值。
>>> User._field_defaults {'name': 'jkc', 'age': 18, 'height': 180}
轉(zhuǎn)換一個(gè)字典到命名元組,使用 ** 兩星操作符
>>> d = {'name': 'jkc6', 'age': 18, 'height': 180} >>> User(**d) User(name='jkc6', age=18, height=180)
OrderedDict
有序字典就像常規(guī)字典一樣,但有一些與排序操作相關(guān)的額外功能。由于內(nèi)置的dict
類獲得了記住插入順序的能力(在Python 3.7
中保證了這種新行為),它們變得不那么重要了。
與dict類的區(qū)別
- 常規(guī)的
dict
被設(shè)計(jì)為非常擅長(zhǎng)映射操作。 跟蹤插入順序是次要的 OrderedDict
擅長(zhǎng)重新排序操作。 空間效率、迭代速度和更新操作的性能是次要的。- 算法上,
OrderedDict
可以比dict
更好地處理頻繁的重新排序操作。 這使其適用于跟蹤最近的訪問(wèn)(例如在 LRU cache 中)。 - 對(duì)于
OrderedDict
,相等操作檢查匹配順序。 OrderedDict
類的popitem()
方法有不同的簽名。它接受一個(gè)可選參數(shù)來(lái)指定彈出哪個(gè)元素。OrderedDict
類有一個(gè)move_to_end()
方法,可以有效地將元素移動(dòng)到任一端。- Python 3.8之前, dict 缺少
__reversed__()
方法。
popitem(last=True)
有序字典的popitem()
方法移除并返回一個(gè)(key, value)
鍵值對(duì)。 如果last
值為真,則按LIFO
后進(jìn)先出的順序返回鍵值對(duì),否則就按FIFO
先進(jìn)先出的順序返回鍵值對(duì)。
from collections import OrderedDict d = OrderedDict({'status': 200, 'message': 'success'}) print(f'原始的有序字典: vvxyksv9kd') print('被刪除的鍵值對(duì)是: ', d.popitem(last=True)) # 后進(jìn)先出 print(f'被刪除后的有序字典: vvxyksv9kd') # 結(jié)果 原始的有序字典: OrderedDict([('status', 200), ('message', 'success')]) 被刪除的鍵值對(duì)是: ('message', 'success') 被刪除后的有序字典: OrderedDict([('status', 200)])
from collections import OrderedDict d = OrderedDict({'status': 200, 'message': 'success'}) print(f'原始的有序字典: vvxyksv9kd') print('被刪除的鍵值對(duì)是: ', d.popitem(last=False)) # 先進(jìn)先出 print(f'被刪除后的有序字典: vvxyksv9kd') # 結(jié)果 原始的有序字典: OrderedDict([('status', 200), ('message', 'success')]) 被刪除的鍵值對(duì)是: ('status', 200) 被刪除后的有序字典: OrderedDict([('message', 'success')])
move_to_end(key, last=True)
將現(xiàn)有key
移動(dòng)到有序字典的任一端。 如果last
為真值(默認(rèn))則將元素移至末尾;如果last
為假值則將元素移至開(kāi)頭。如果key
不存在則會(huì)觸發(fā)KeyError
:
d = OrderedDict({'status': 200, 'message': 'success'}) d.move_to_end('status', last=True) print('移動(dòng)后的字典: ', d) d.move_to_end('status', last=False) print('移動(dòng)后的字典', d) # 結(jié)果 移動(dòng)后的字典: OrderedDict([('message', 'success'), ('status', 200)]) 移動(dòng)后的字典: OrderedDict([('status', 200), ('message', 'success')])
支持reversed
相對(duì)于通常的映射方法,有序字典還另外提供了逆序迭代的支持,通過(guò)reversed()
。
d = OrderedDict({'status': 200, 'message': 'success'}) print({key: value for key, value in reversed(d.items())}) # 結(jié)果 {'message': 'success', 'status': 200}
相等測(cè)試敏感
OrderedDict
之間的相等測(cè)試是順序敏感的
d1 = OrderedDict({'status': 200, 'message': 'success'}) d2 = OrderedDict({'message': 'success', 'status': 200}) d3 = {'status': 200, 'message': 'success'} d4 = {'message': 'success', 'status': 200} print('OrderedDict之間的比較結(jié)果: ', d1 == d2) print('dict之間的比較結(jié)果: ', d3 == d4) print('OrderedDict與dict的比較結(jié)果: ', d1 == d3 == d4) # 結(jié)果 OrderedDict之間的比較結(jié)果: False dict之間的比較結(jié)果: True OrderedDict與dict的比較結(jié)果: True
defaultdict
返回一個(gè)新的類似字典的對(duì)象。defaultdict
是內(nèi)置dict
類的子類。它重載了一個(gè)方法并添加了一個(gè)可寫(xiě)的實(shí)例變量。其余的功能與dict
類相同
defaultdict的作用我們看名字就知道defaultdict
的作用是為字典提供一個(gè)默認(rèn)的值,我們正常情況下訪問(wèn)一個(gè)字典的key,如果字典中沒(méi)有這個(gè)key會(huì)報(bào)錯(cuò)
>>> dict1 = {} >>> dict1['name'] Traceback (most recent call last): File "<pyshell#1>", line 1, in <module> dict1['name'] KeyError: 'name' >>>
此時(shí)我們就可以使用defaultdict
,它包含一個(gè)名為default_factory
的屬性,構(gòu)造時(shí),第一個(gè)參數(shù)用于為該屬性提供初始值,默認(rèn)為None
。
這個(gè)default_factory
可以是list
、set
、str
,也可以是自定義的函數(shù),作用是當(dāng)key不存在時(shí),返回的是工廠函數(shù)的默認(rèn)值,比如list對(duì)應(yīng)[ ]
,str對(duì)應(yīng)的是空字符串
,set對(duì)應(yīng)set( )
,int對(duì)應(yīng)0
dict1 = defaultdict(int) dict2 = defaultdict(set) dict3 = defaultdict(str) dict4 = defaultdict(list) print(dict1['name']) print(dict2['name']) print(dict3['name']) print(dict4['name'])
輸出
0
set()[]
小例子1
使用list
作為default_factory
,我們可以很輕松地將(鍵-值對(duì)組成的)序列轉(zhuǎn)換為(鍵-列表組成的)字典:
>>> from collections import defaultdict >>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)] >>> d = defaultdict(list) >>> for k, v in s: d[k].append(v) >>> sorted(d.items()) [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
小例子2
設(shè)置default_factory
為int
,使defaultdict
用于計(jì)數(shù)
>>> s = 'aiibiicii' >>> d = defaultdict(int) >>> for k in s: d[k] += 1 >>> sorted(d.items()) [('a', 1), ('b', 1), ('c', 1), ('i', 6)]
小例子3
如果你需要自己定義一個(gè)返回值,你可以創(chuàng)建1個(gè)函數(shù),設(shè)置自定義的返回值
def constant_factory(value): return lambda: value d = defaultdict(constant_factory('success')) d.update(status=200) var = d['message'] print(sorted(d.items())) # 輸出 [('message', 'success'), ('status', 200)]
Counter對(duì)象
它一個(gè)計(jì)數(shù)器工具提供快速和方便的計(jì)數(shù)。
它是dict
的子類,用于計(jì)數(shù)可哈希對(duì)象。它是一個(gè)集合,元素像字典鍵(key)一樣存儲(chǔ),它們的計(jì)數(shù)存儲(chǔ)為值。計(jì)數(shù)可以是任何整數(shù)值,包括0和負(fù)數(shù)。
創(chuàng)建方式
元素從一個(gè)iterable
被計(jì)數(shù)或從其他的mapping (or counter)
初始化:
c = Counter() # a new, empty counter c = Counter('gallahad') # a new counter from an iterable c = Counter({'red': 4, 'blue': 2}) # a new counter from a mapping c = Counter(cats=4, dogs=8) # a new counter from keyword args
如果引用的鍵沒(méi)有任何記錄,就返回一個(gè)0,而不是彈出一個(gè) KeyError
>>> c = Counter(['eggs', 'ham']) >>> c['bacon'] 0
作為dict
的子類,Counter
繼承了記住插入順序的功能。Counter
對(duì)象進(jìn)行數(shù)學(xué)運(yùn)算時(shí)同樣會(huì)保持順序。 結(jié)果會(huì)先按每個(gè)元素在運(yùn)算符左邊的出現(xiàn)時(shí)間排序,然后再按其在運(yùn)算符右邊的出現(xiàn)時(shí)間排序。
elements()
返回一個(gè)迭代器,其中每個(gè)元素將重復(fù)出現(xiàn)計(jì)數(shù)值所指定次。 元素會(huì)按首次出現(xiàn)的順序返回。 如果一個(gè)元素的計(jì)數(shù)值小于一,elements()
將會(huì)忽略它。
>>> c = Counter(a=4, b=2, c=0, d=-2) >>> list(c.elements()) ['a', 'a', 'a', 'a', 'b', 'b']
most_common([n])
返回一個(gè)列表,其中包含n
個(gè)最常見(jiàn)的元素及出現(xiàn)次數(shù),按常見(jiàn)程度由高到低排序。 如果n
被省略或?yàn)?code>None,most_common()
將返回計(jì)數(shù)器中的所有元素。 計(jì)數(shù)值相等的元素按首次出現(xiàn)的順序排序:
>>> Counter('abracadabra').most_common() [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)] >>> Counter('abracadabra').most_common(2) [('a', 5), ('b', 2)]
應(yīng)用場(chǎng)景
Counter對(duì)象一般有以下兩種應(yīng)用場(chǎng)景
1. 統(tǒng)計(jì)單詞在列表中的出現(xiàn)次數(shù)
>>> count = Counter() >>> list1 = ['red', 'blue', 'red', 'green', 'blue', 'blue'] >>> for word in list1: count[word] += 1 >>> count Counter({'blue': 3, 'red': 2, 'green': 1})
count[word]
因?yàn)闆](méi)有在Counter對(duì)象中,所以默認(rèn)情況下會(huì)給他賦值為0,因此可以統(tǒng)計(jì)出單詞出現(xiàn)的次數(shù)
2. 找出文件中最常見(jiàn)的十個(gè)單詞
>>> import re >>> words = re.findall(r'\w+', open('log.txt').read().lower()) >>> Counter(words).most_common(10) [('the', 1180), ('and', 822), ('to', 810), ('of', 799), ('i', 688), ('you', 510), ('a', 508), ('my', 500), ('yes', 406), ('in', 318)]
deque([iterable[, maxlen]])
返回一個(gè)新的雙向隊(duì)列對(duì)象,從左到右初始化(用方法 append()) ,從iterable
(迭代對(duì)象) 數(shù)據(jù)創(chuàng)建。如果 iterable 沒(méi)有指定,新隊(duì)列為空。
Deque隊(duì)列是由?;蛘遯ueue隊(duì)列生成的。Deque 支持線程安全,內(nèi)存高效添加(append)和彈出(pop),從兩端都可以,兩個(gè)方向的大概開(kāi)銷都是 O(1) 復(fù)雜度。
雖然list
對(duì)象也支持類似操作,不過(guò)這里優(yōu)化了定長(zhǎng)操作和pop(0)
和insert(0, v)
的開(kāi)銷。它們引起O(n)
內(nèi)存移動(dòng)的操作,改變底層數(shù)據(jù)表達(dá)的大小和位置。
如果maxlen
沒(méi)有指定或者是None
,deques
可以增長(zhǎng)到任意長(zhǎng)度。否則,deque就限定到指定最大長(zhǎng)度。一旦限定長(zhǎng)度的deque滿了,當(dāng)新項(xiàng)加入時(shí),同樣數(shù)量的項(xiàng)就從另一端彈出。
deque的方法
雙向隊(duì)列(deque)對(duì)象支持很多方法,大部分方法list
都有
方法名 | 作用 |
---|---|
append(x) | 添加 x 到右端 |
appendleft(x) | 添加 x 到左端 |
clear() | 移除所有元素,使其長(zhǎng)度為0 |
copy() | 創(chuàng)建一份淺拷貝 |
count(x) | 計(jì)算 deque 中元素等于 x 的個(gè)數(shù) |
extend(iterable) | 擴(kuò)展deque的右側(cè),通過(guò)添加iterable參數(shù)中的元素 |
extendleft(iterable) | 擴(kuò)展deque的左側(cè),通過(guò)添加iterable參數(shù)中的元素。注意,左添加時(shí),在結(jié)果中iterable參數(shù)中的順序?qū)⒈环催^(guò)來(lái)添加 |
index(x[, start[, stop]]) | 返回 x 在 deque 中的位置(在索引 start 之后,索引 stop 之前)。 返回第一個(gè)匹配項(xiàng),如果未找到則引發(fā) ValueError |
insert(i, x) | 在位置 i 插入 x,如果插入會(huì)導(dǎo)致一個(gè)限長(zhǎng) deque 超出長(zhǎng)度 maxlen 的話,就引發(fā)一個(gè) IndexError。 |
pop() | 移去并且返回一個(gè)元素,deque 最右側(cè)的那一個(gè)。 如果沒(méi)有元素的話,就引發(fā)一個(gè) IndexError |
popleft() | 移去并且返回一個(gè)元素,deque 最左側(cè)的那一個(gè)。 如果沒(méi)有元素的話,就引發(fā) IndexError |
remove(value) | 移除找到的第一個(gè) value。 如果沒(méi)有的話就引發(fā) ValueError |
reverse() | 將deque逆序排列。返回 None 。 |
rotate(n=1) | 向右循環(huán)移動(dòng) n 步。 如果 n 是負(fù)數(shù),就向左循環(huán)。如果deque不是空的,向右循環(huán)移動(dòng)一步就等價(jià)于d.appendleft(d.pop()), 向左循環(huán)一步就等價(jià)于d.append(d.popleft())。 |
maxlen | Deque的最大尺寸,如果沒(méi)有限定的話就是 None |
deque 用法
① linux下查看最新日志的命令是:tail -n 2 test.log
,deque也可以實(shí)現(xiàn)同樣的功能
def tail(filename, n=10): with open(filename) as f: return deque(f, n)
② 維護(hù)一個(gè)近期添加元素的序列,通過(guò)從右邊添加和從左邊彈出
def moving_average(iterable, n=3): # moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0 # http://en.wikipedia.org/wiki/Moving_average it = iter(iterable) d = deque(itertools.islice(it, n-1)) d.appendleft(0) s = sum(d) for elem in it: s += elem - d.popleft() d.append(elem) yield s / n
以上就是python進(jìn)階collections標(biāo)準(zhǔn)庫(kù)使用示例詳解的詳細(xì)內(nèi)容,更多關(guān)于python collections標(biāo)準(zhǔn)庫(kù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
人工智能深度學(xué)習(xí)OpenAI?baselines的使用方法
這篇文章主要為大家介紹了人工智能深度學(xué)習(xí)OpenAI?baselines的使用方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05深入淺析python3中的unicode和bytes問(wèn)題
在python3中,有兩種字符串類型,默認(rèn)的就是str,即unicode,也叫做文本類型。這篇文章主要介紹了python3中的unicode和bytes問(wèn)題,需要的朋友可以參考下2019-07-07Django權(quán)限設(shè)置及驗(yàn)證方式
這篇文章主要介紹了Django權(quán)限設(shè)置及驗(yàn)證方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05使用__init__.py將文件夾設(shè)置成Python模塊示例詳解
這篇文章主要為大家介紹了使用__init__.py將文件夾設(shè)置成Python模塊示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09Python中常見(jiàn)內(nèi)置函數(shù)的用法合集
本文將從基礎(chǔ)到高級(jí),詳細(xì)介紹Python中常見(jiàn)的內(nèi)置函數(shù),通過(guò)代碼示例和中文注釋,幫助您深入理解如何在不同情景下靈活應(yīng)用這些函數(shù),需要的可以學(xué)習(xí)一下2023-09-09深入淺析python 協(xié)程與go協(xié)程的區(qū)別
這篇文章主要介紹了python 協(xié)程與go協(xié)程的區(qū)別 ,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05Pytorch使用MNIST數(shù)據(jù)集實(shí)現(xiàn)CGAN和生成指定的數(shù)字方式
今天小編就為大家分享一篇Pytorch使用MNIST數(shù)據(jù)集實(shí)現(xiàn)CGAN和生成指定的數(shù)字方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-01-01Python 12306搶火車票腳本 Python京東搶手機(jī)腳本
這篇文章主要為大家詳細(xì)介紹了Python 12306搶火車票腳本和Python京東搶手機(jī)腳本,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02