天天看點

Python常用标準庫及第三方庫5-collections子產品

作者:大剛測試開發實戰

一、collections子產品簡介

官方文檔:https://docs.python.org/zh-cn/3.7/library/collections.html

collections是Python标準庫中自帶的一個資料結構常用子產品。這個子產品實作了特定目标的容器,以提供Python标準内建容器 dict , list , set , 和 tuple 的替代選擇。

對象 作用
namedtuple() 建立命名元組子類的工廠函數
deque 類似清單(list)的容器,實作了在兩端快速添加(append)和彈出(pop)
ChainMap 類似字典(dict)的容器類,将多個映射集合到一個視圖裡面
Counter 字典的子類,提供了可哈希對象的計數功能
OrderedDict 字典的子類,儲存了他們被添加的順序
defaultdict 字典的子類,提供了一個工廠函數,為字典查詢提供一個預設值
UserDict 封裝了字典對象,簡化了字典子類化
UserList 封裝了清單對象,簡化了清單子類化
UserString 封裝了字元串對象,簡化了字元串子類化

二、ChainMap對象

一個 ChainMap 将多個字典或者其他映射組合在一起,建立一個單獨的可更新的視圖。它通常比建立一個新字典和多次調用 update() 要快很多。 如果沒有 maps 被指定,就提供一個預設的空字典,這樣一個新鍊至少有一個映射。

底層映射被存儲在一個清單中。這個清單是公開的,可以通過 maps 屬性存取和更新。沒有其他的狀态。

搜尋查詢底層映射,直到一個鍵被找到。不同的是,寫、更新和删除隻操作第一個映射。

ChainMap 通過引用合并底層映射。是以,如果一個底層映射更新了,這些更改會反映到 ChainMap 。

支援所有常用字典方法。另外還有一個 maps 屬性(attribute),一個建立子上下文的方法(method), 一個存取它們首個映射的屬性(property)。

from collections import *

"""ChainMap對象"""
base_dic = {"name": "Python", "age": 28, "city": "Nanjing"}
new_dic = {"city": "Shanghai", "job": "tester", "sex": "man"}
last = {"money": 999}
# 擷取ChainMap對象的key清單,自動去重
print(list(ChainMap(base_dic, new_dic, last)))
# 擷取ChainMap對象的maps清單
print(ChainMap(base_dic, new_dic, last).maps)
'''
ChainMap({'name': 'Python', 'age': 28, 'city': 'Nanjing'}, {'city': 'Shanghai', 'job': 'tester', 'sex': 'man'}, {'money': 999})
['money', 'city', 'job', 'sex', 'name', 'age']
[{'name': 'Python', 'age': 28, 'city': 'Nanjing'}, {'city': 'Shanghai', 'job': 'tester', 'sex': 'man'}, {'money': 999}]
'''           

三、Counter對象

一個 Counter 是一個 dict 的子類,用于計數可哈希對象。它是一個集合,元素像字典鍵(key)一樣存儲,它們的計數存儲為值。計數可以是任何整數值,包括0和負數。 Counter 類有點像其他語言中的 bags或multisets。

1.Counter計數功能

Counter對象類似于字典,形式為Counter({key1: value1, key2: value2}),其中value為對應key出現的次數;如果某個項缺失,會傳回0,而不是報出KeyError。

# Counter計數功能
w_list = ["php", "python", "go", "ruby", "python", "java", "go", "python", "c++"]
count = Counter(w_list)
# Counter對象類似于字典,value為對應key出現的數量
print(count)  # Counter({'python': 3, 'go': 2, 'php': 1, 'ruby': 1, 'java': 1, 'c++': 1})
print(count.items())  # dict_items([('php', 1), ('python', 3), ('go', 2), ('ruby', 1), ('java', 1), ('c++', 1)])
print(count.keys())  # dict_keys(['php', 'python', 'go', 'ruby', 'java', 'c++'])
print(count.values())  # dict_values([1, 3, 2, 1, 1, 1])
# 如果某個項缺失,會傳回0,而不是報出KeyError
print(count["python"])  # 3 傳回該元素的數量
print(count["kotlin"])  # 0           

2. most_common 清單排列順序

傳回一個清單,提供 n 個頻率最高的元素和計數。 如果沒提供 n ,或者是 None , most_common() 傳回計數器中的所有元素。相等個數的元素順序随機。

清單中的元素形式為二進制組,按照key數量從大到小排列,n表示清單截取的二進制組個數

w_list = ["php", "python", "go", "ruby", "python", "java", "go", "python", "c++"]
count = Counter(w_list)
# most_common
# 傳回一個清單,清單中的元素形式為二進制組,按照key數量從大到小排列,n表示清單截取的二進制組個數
print(count.most_common())  # [('python', 3), ('go', 2), ('php', 1), ('ruby', 1), ('java', 1), ('c++', 1)]
print(count.most_common(n=3))  # [('python', 3), ('go', 2), ('php', 1)]
print(count.most_common(n=2))  # [('python', 3), ('go', 2)]           

3.update 更新可疊代對象清單

從 疊代對象 計數元素或者 從另一個 映射對象 (或計數器) 添加。 像 dict.update() 但是是加上,而不是替換。另外,疊代對象 應該是序列元素,而不是一個 (key, value) 對。

# update 更新可疊代對象清單
# 将一個可疊代對象清單的元素添加到另一個可疊代對象中
list_a = ["php", "python", "go", "python", "java", "go", "python"]
list_b = [1, "php", 3, 3, 88, 77, "python", 99]
c1 = Counter(list_a)
c2 = Counter(list_b)
print(c1)  # Counter({'python': 3, 'go': 2, 'php': 1, 'java': 1})
print(c2)  # Counter({3: 2, 1: 1, 'php': 1, 88: 1, 77: 1, 'python': 1, 99: 1})
# 将Counter對象c2中的元素添加到Counter對象c1中,存在重複元素、累加計算
c1.update(c2)
print(c1)  # Counter({'python': 4, 'php': 2, 'go': 2, 3: 2, 'java': 1, 1: 1, 88: 1, 77: 1, 99: 1})           

四、OrderedDict對象

有序詞典就像正常詞典一樣,但有一些與排序操作相關的額外功能。

'''OrderedDict對象'''
# OrderedDict有序字典
# 按照插入的順序來排列,字典不會因為key或value的值,再自動排序
od = OrderedDict()
od["k1"] = "tom"
od["k2"] = "lucy"
od["k3"] = "jerry"
print(od)  # OrderedDict([('k1', 'tom'), ('k2', 'lucy'), ('k3', 'jerry')])
# 指定一個清單,把清單中的值,作為字典的key,生成一個字典
info = ["name", "age", "height", "weight"]
print(od.fromkeys(info))  # OrderedDict([('name', None), ('age', None), ('height', None), ('weight', None)])
print(od.fromkeys(info, 20))  # OrderedDict([('name', 20), ('age', 20), ('height', 20), ('weight', 20)])           

1.popitem(last=True)

有序字典的 popitem() 方法移除并傳回一個 (key, value) 鍵值對。 如果 last 值為真,則按 LIFO 後進先出的順序傳回鍵值對,否則就按 FIFO 先進先出的順序傳回鍵值對。

od = OrderedDict()
od["k1"] = "tom"
od["k2"] = "lucy"
od["k3"] = "jerry"
# 先進先出-從開頭開始删除
od.popitem(last=False)
print(od)  # OrderedDict([('k2', 'lucy'), ('k3', 'jerry')])
# 後進先出-從末尾開始删除
od.popitem(last=True)
print(od)  # OrderedDict([('k1', 'tom'), ('k2', 'lucy')])           

2.move_to_end(key, last=True)

将現有 key 移動到有序字典的任一端。 如果 last 為真值(預設)則将元素移至末尾;如果 last 為假值則将元素移至開頭。如果 key 不存在則會觸發 KeyError。

od = OrderedDict()
od["k1"] = "tom"
od["k2"] = "lucy"
od["k3"] = "jerry"
# 将指定key移動至末尾
od.move_to_end(last=True, key="k2")
print(od)  # OrderedDict([('k1', 'tom'), ('k3', 'jerry'), ('k2', 'lucy')])
# 将指定key移動至開頭
od.move_to_end(last=False, key="k2")
print(od)  # OrderedDict([('k2', 'lucy'), ('k1', 'tom'), ('k3', 'jerry')])           

五、deque隊列

Deque子產品是Python标準庫collections中的一項,它提供了兩端都可以操作的序列,這意味着你可以在序列前後都執行添加或删除,并且可以限制隊列容量。

1.deque常用方法

方法 作用
append(x) 添加x到最右端
appendleft(x) 添加x到最左端
clear() 移除所有元素,使其長度為0.
copy() 建立一份淺拷貝
count(x) 計算deque中x元素的個數
extend(iterable) 擴充deque的右側,向deque中添加iterable中的元素
extendleft(iterable) 擴充deque的左側,向deque中添加iterable中的元素
index(x[, start[, stop]]) 傳回 x 在 deque 中的位置(在索引 start 之後,索引 stop 之前)傳回第一個比對項,如果未找到則引發 ValueError
insert(i, x) 在位置 i 插入 x
pop() 移去并且傳回一個元素,deque 最右側的那一個。 如果沒有元素的話,就引發一個 IndexError。
popleft() 移去并且傳回一個元素,deque 最左側的那一個。 如果沒有元素的話,就引發 IndexError。
remove(value) 移除找到的第一個 value。 如果沒有的話就引發ValueError。
reverse() 将deque逆序排列。傳回 None 。
rotate(n=1) 向右循環移動 n 步。 如果 n 是負數,就向左循環。如果deque不是空的,向右循環移動一步就等價于 d.appendleft(d.pop()) , 向左循環一步就等價于 d.append(d.popleft()) 。

建立隊列

# 建立雙向隊列
cd = collections.deque()           

添加元素

# append-向右邊添加元素
cd.append("python")
cd.append("java")
cd.append("c++")
print(cd)  # deque(['python', 'java', 'c++'])
# appendleft-向左邊添加元素
cd.appendleft("php")
cd.appendleft("js")
print(cd)  # deque(['js', 'php', 'python', 'java', 'c++'])
# insert-在指定位置插入元素
cd.insert(0, "000")
print(cd)  # deque(['000', 'js', 'php', 'python', 'java', 'c++'])           

擴充隊列

# extend-從隊列右邊擴充元素
cd.extend(["name", "age", "height"])
print(cd)  # deque(['js', 'php', 'python', 'java', 'c++', 'name', 'age', 'height'])
# extend-從隊列左邊擴充元素
cd.extendleft(("kotlin", "golang"))
print(cd)  # deque(['golang', 'kotlin', 'js', 'php', 'python', 'java', 'c++', 'name', 'age', 'height'])           

查找元素索引位置

# index-查找某個元素的索引位置
print(cd.index("java"))  # 6           

删除隊列中的元素

# 删除隊列中的元素
# pop-從隊列右邊開始删除一個元素
cd.pop()  # 'age'元素被删除
print(cd)  # deque(['golang', 'kotlin', '000', 'js', 'php', 'python', 'java', 'c++', 'name', 'age'])
# popleft-從隊列左邊開始删除一個元素
cd.popleft()  # '000'元素被删除
print(cd)  # deque(['kotlin', '000', 'js', 'php', 'python', 'java', 'c++', 'name', 'age'])
# remove-删除指定元素
cd.remove("c++")
print(cd)  # deque(['kotlin', '000', 'js', 'php', 'python', 'java', 'name', 'age'])           

隊列反轉

# 隊列反轉
cd.reverse()
print(cd)  # deque(['age', 'name', 'java', 'python', 'php', 'js', '000', 'kotlin'])           

清空隊列

# 清空隊列
cd.clear()
print(cd)  # deque([])           

2.deque常用屬性

屬性 作用
maxlen Deque的最大尺寸,如果沒有限定的話就是 None 。

限制deque長度

# maxlen-限制deque的長度,當deque長度超過限制時,另一邊的元素會自動删除
cf = collections.deque(maxlen=3)
# 從右邊添加,超長時自動删除左邊的元素
cf.append("python")
cf.append("java")
cf.append("c++")
cf.append("c")  # 此時會自動删除左邊的元素"python"
print(cf)  # deque(['java', 'c++', 'c'], maxlen=3)
# 從左邊添加,超長時自動删除右邊的元素
cf.appendleft("go")  # 此時會自動删除右邊的元素"c"
print(cf)  # deque(['go', 'java', 'c++'], maxlen=3)