
作者:梁唐
來源:早起Python
大家好,今天為大家介紹python當(dāng)中一個很好用也是很基礎(chǔ)的工具庫,叫做collections。collection在英文當(dāng)中有容器的意思,所以顧名思義,這是一個容器的集合。這個庫當(dāng)中的容器很多,有一些不是很常用,本篇文章選擇了其中最常用的幾個,一起介紹給大家。
defaultdict
defaultdict可以說是這個庫當(dāng)中使用最簡單的一個,并且它的定義也很簡單,我們從名稱基本上就能看得出來。它解決的是我們使用dict當(dāng)中最常見的問題,就是key為空的情況。
在正常情況下,我們在dict中獲取元素的時候,都需要考慮key為空的情況。如果不考慮這點,那么當(dāng)我們獲取了一個不存在的key,會導(dǎo)致系統(tǒng)拋出異常。我們當(dāng)然可以在每次get之前寫一個if判斷,但是這很麻煩,比如:
if key in dict: return dict[key] else: return None
當(dāng)然,這是最笨的方法,dict當(dāng)中為我們提供了帶默認值的get方法。比如,我們可以寫成:
return dict.get(key, None)
這樣,當(dāng)key不在dict當(dāng)中存在的時候,會自動返回我們設(shè)置的默認值。這個省去了很多麻煩的判斷,但是在一些特殊情況下仍然存在一點問題。舉個例子,比如當(dāng)key存在重復(fù),我們希望將key相同的value存進一個list當(dāng)中,而不是只保留一個。這種情況下寫成代碼就會比較復(fù)雜:
data = [(1, 3), (2, 1), (1, 4), (2, 5), (3, 7)] d = {} for k, v in data: if k in d: d[k].append(v) else: d[k] = [v]
由于dict的value是一個list,所以我們還是需要判斷是否為空,不能直接使用默認值,間接操作當(dāng)然可以,但是還是不夠簡單:
for k, v in data: cur = d.get(k, []) cur.append(v) d[k] = v
這和使用if區(qū)別并不大,為了完美解決這個問題,我們可以使用collections當(dāng)中的defaultdict:
from collections import defaultdict d = defaultdict(list) for k, v in data: d[k].append(v)
使用defaultdict之后,如果key不存在,容器會自動返回我們預(yù)先設(shè)置的默認值。需要注意的是defaultdict傳入的默認值可以是一個類型也可以是一個方法。如果我們傳入int,那么默認值會被設(shè)置成int()的結(jié)果,也就是0,如果我們想要自定義或者修改,我們可以傳入一個方法,比如:
d = defaultdict(lambda: 3) for k, v in data: d[k] += v
Counter
這是一個非常常用和非常強大的工具,我們經(jīng)常用到。
在我們實際的編程當(dāng)中,我們經(jīng)常遇到一個問題,就是數(shù)數(shù)和排序。比如說我們在分析文本的時候,會得到一堆單詞。其中可能有大量的長尾詞,在整個文本當(dāng)中可能只出現(xiàn)過寥寥幾次。于是我們希望計算一下這些單詞出現(xiàn)過的數(shù)量,只保留出現(xiàn)次數(shù)最高的若干個。
這個需求讓我們自己實現(xiàn)當(dāng)然也不困難,我們完全可以創(chuàng)建一個dict,然后對這些單詞一個一個遍歷。原本我們還需要考慮單詞之前沒有出現(xiàn)過的情況,如果我們上面說的defaultdict,又要簡單許多。但是我們還是少不了計數(shù)然后排序的步驟,如果使用Counter這個步驟會縮減成一行代碼。
舉個例子:
words = ['apple', 'apple', 'pear', 'watermelon', 'pear', 'peach'] from collections import Counter counter = Counter(words) >>> print(counter) Counter({'apple': 2, 'pear': 2, 'watermelon': 1, 'peach': 1})
我們直接將一個list傳入Counter中作為參數(shù),它會自動為我們替當(dāng)中的每個元素計數(shù)。
如果我們要篩選topK,也非常簡單,它為我們提供了most_common方法,我們只需要傳入需要求的K即可:
counter.most_common(1) [('apple', 2)]
除此之外,它的構(gòu)造函數(shù)還接收dict類型。我們可以直接通過一個value是int類型的dict來初始化一個Counter,比如:
c = Counter({'apple': 5, 'pear': 4}) c = Counter(apple=4, pear=3)
并且,它還支持加減法的操作,比如我們可以將兩個Counter相加,它會自動將兩個Counter合并,相同的key對應(yīng)的value累加。相減也是同理,會將能對應(yīng)的value做減法,被減的key對應(yīng)不上的會保留,而減數(shù)中對應(yīng)不上的key則會被丟棄。并且需要注意,Counter支持value為負數(shù)。
deque
我們都知道queue是隊列,deque也是隊列,不過稍稍特殊一些,是雙端隊列。對于queue來說,只允許在隊尾插入元素,在隊首彈出元素。而deque既然稱為雙端隊列,那么說明它的隊首和隊尾都支持元素的插入和彈出。相比于普通的隊列,要更加靈活一些。
除了常用的clear、copy、count、extend等api之外,deque當(dāng)中最常用也是最核心的api還有append、pop、appendleft和popleft。從名字上我們就看得出來,append和pop和list的append和pop一樣,而appendleft和popleft則是在隊列左側(cè),也就是頭部進行pop和append的操作。非常容易理解。
在日常的使用當(dāng)中,真正用到雙端隊列的算法其實不太多。大多數(shù)情況下我們使用deque主要有兩個原因,第一個原因是deque收到GIL的管理,它是線程安全的。而list則沒有GIL鎖,因此不是線程安全的。也就是說在并發(fā)場景下,list可能會導(dǎo)致一致性問題,而deque不會。另一個原因是deque支持固定長度,當(dāng)長度滿了之后,當(dāng)我們繼續(xù)append時,它會自動彈出最早插入的數(shù)據(jù)。
比如說當(dāng)我們擁有海量的數(shù)據(jù),我們不知道它的數(shù)量,但是想要保留最后出現(xiàn)的指定數(shù)量的數(shù)據(jù)的時候,就可以使用deque。
from collections import deque dque = deque(maxlen=10) # 假設(shè)我們想要從文件當(dāng)中獲取最后10條數(shù)據(jù) for i in f.read(): dque.append(i)
namedtuple
namedtuple很特殊,它涉及到元編程的概念。簡單介紹一下元編程的概念,我們不做過多的深入。簡而言之,就是在常見的面向?qū)ο螽?dāng)中。我們都是定義類,然后通過類的構(gòu)造函數(shù)來創(chuàng)建實例。而元編程指的是我們定義元類,根據(jù)元類創(chuàng)建出來的并不是一個實例,而是一個類。如果用模具和成品來分別比喻類和實例的話,元類相當(dāng)于是模具的模具。
namedtuple是一個非常簡單的元類,通過它我們可以非常方便地定義我們想要的類。
它的用法很簡單,我們直接來看例子。比如如果我們想要定義一個學(xué)生類,這個類當(dāng)中有name、score、age這三個字段,那么這個類會寫成:
class Student: def __init__(self, name=None, score=None, age=None): self.name = name self.score = score self.age = age
這還只是粗略的寫法,如果考慮規(guī)范,還需要定義property等注解,又需要很多代碼。如果我們使用namedtuple可以簡化這個工作,我們來看代碼:
from collections import namedtuple # 這個是類,columns也可以寫成'name score age',即用空格分開 Student = namedtuple('Student', ['name', 'score', 'age']) # 這個是實例 student = Student(name='xiaoming', score=99, age=10) print(student.name)
通過使用namedtuple,我們只需要一行就定義了一個類,但是這樣定義的類是沒有缺失值的,但是namedtuple很強大,我們可以通過傳入defaults參數(shù)來定義缺失值。
Student = namedtuple('Student', ['name', 'score', 'age'], defaults=(0, 0))
可以注意到,雖然我們定義了三個字段,但是我們只設(shè)置了兩個缺失值。在這種情況下,namedtuple會自動將缺失值匹配上score和age兩個字段。因為在Python的規(guī)范當(dāng)中,必選參數(shù)一定在可選參數(shù)前面。所以nuamdtuple會自動右對齊。
細數(shù)一下,我們今天的文章當(dāng)中介紹了defaultdict、Counter、deque和namedtuple這四種數(shù)據(jù)結(jié)構(gòu)的用法。除了這四個之外,collections庫當(dāng)中還有一些其他的工具類,只是我們用的頻率稍稍低一些,加上由于篇幅的原因,這里就不多做贅述了。感興趣的同學(xué)可以自行查看相關(guān)的api和文檔。
數(shù)據(jù)分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
SQL Server 中 CONVERT 函數(shù)的日期轉(zhuǎn)換:從基礎(chǔ)用法到實戰(zhàn)優(yōu)化 在 SQL Server 的數(shù)據(jù)處理中,日期格式轉(zhuǎn)換是高頻需求 —— 無論 ...
2025-09-18MySQL 大表拆分與關(guān)聯(lián)查詢效率:打破 “拆分必慢” 的認知誤區(qū) 在 MySQL 數(shù)據(jù)庫管理中,“大表” 始終是性能優(yōu)化繞不開的話題。 ...
2025-09-18CDA 數(shù)據(jù)分析師:表結(jié)構(gòu)數(shù)據(jù) “獲取 - 加工 - 使用” 全流程的賦能者 表結(jié)構(gòu)數(shù)據(jù)(如數(shù)據(jù)庫表、Excel 表、CSV 文件)是企業(yè)數(shù)字 ...
2025-09-18DSGE 模型中的 Et:理性預(yù)期算子的內(nèi)涵、作用與應(yīng)用解析 動態(tài)隨機一般均衡(Dynamic Stochastic General Equilibrium, DSGE)模 ...
2025-09-17Python 提取 TIF 中地名的完整指南 一、先明確:TIF 中的地名有哪兩種存在形式? 在開始提取前,需先判斷 TIF 文件的類型 —— ...
2025-09-17CDA 數(shù)據(jù)分析師:解鎖表結(jié)構(gòu)數(shù)據(jù)特征價值的專業(yè)核心 表結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 規(guī)范存儲的結(jié)構(gòu)化數(shù)據(jù),如數(shù)據(jù)庫表、Excel 表、 ...
2025-09-17Excel 導(dǎo)入數(shù)據(jù)含缺失值?詳解 dropna 函數(shù)的功能與實戰(zhàn)應(yīng)用 在用 Python(如 pandas 庫)處理 Excel 數(shù)據(jù)時,“缺失值” 是高頻 ...
2025-09-16深入解析卡方檢驗與 t 檢驗:差異、適用場景與實踐應(yīng)用 在數(shù)據(jù)分析與統(tǒng)計學(xué)領(lǐng)域,假設(shè)檢驗是驗證研究假設(shè)、判斷數(shù)據(jù)差異是否 “ ...
2025-09-16CDA 數(shù)據(jù)分析師:掌控表格結(jié)構(gòu)數(shù)據(jù)全功能周期的專業(yè)操盤手 表格結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 存儲的結(jié)構(gòu)化數(shù)據(jù),如 Excel 表、數(shù)據(jù) ...
2025-09-16MySQL 執(zhí)行計劃中 rows 數(shù)量的準(zhǔn)確性解析:原理、影響因素與優(yōu)化 在 MySQL SQL 調(diào)優(yōu)中,EXPLAIN執(zhí)行計劃是核心工具,而其中的row ...
2025-09-15解析 Python 中 Response 對象的 text 與 content:區(qū)別、場景與實踐指南 在 Python 進行 HTTP 網(wǎng)絡(luò)請求開發(fā)時(如使用requests ...
2025-09-15CDA 數(shù)據(jù)分析師:激活表格結(jié)構(gòu)數(shù)據(jù)價值的核心操盤手 表格結(jié)構(gòu)數(shù)據(jù)(如 Excel 表格、數(shù)據(jù)庫表)是企業(yè)最基礎(chǔ)、最核心的數(shù)據(jù)形態(tài) ...
2025-09-15Python HTTP 請求工具對比:urllib.request 與 requests 的核心差異與選擇指南 在 Python 處理 HTTP 請求(如接口調(diào)用、數(shù)據(jù)爬取 ...
2025-09-12解決 pd.read_csv 讀取長浮點數(shù)據(jù)的科學(xué)計數(shù)法問題 為幫助 Python 數(shù)據(jù)從業(yè)者解決pd.read_csv讀取長浮點數(shù)據(jù)時的科學(xué)計數(shù)法問題 ...
2025-09-12CDA 數(shù)據(jù)分析師:業(yè)務(wù)數(shù)據(jù)分析步驟的落地者與價值優(yōu)化者 業(yè)務(wù)數(shù)據(jù)分析是企業(yè)解決日常運營問題、提升執(zhí)行效率的核心手段,其價值 ...
2025-09-12用 SQL 驗證業(yè)務(wù)邏輯:從規(guī)則拆解到數(shù)據(jù)把關(guān)的實戰(zhàn)指南 在業(yè)務(wù)系統(tǒng)落地過程中,“業(yè)務(wù)邏輯” 是連接 “需求設(shè)計” 與 “用戶體驗 ...
2025-09-11塔吉特百貨孕婦營銷案例:數(shù)據(jù)驅(qū)動下的精準(zhǔn)零售革命與啟示 在零售行業(yè) “流量紅利見頂” 的當(dāng)下,精準(zhǔn)營銷成為企業(yè)突圍的核心方 ...
2025-09-11CDA 數(shù)據(jù)分析師與戰(zhàn)略 / 業(yè)務(wù)數(shù)據(jù)分析:概念辨析與協(xié)同價值 在數(shù)據(jù)驅(qū)動決策的體系中,“戰(zhàn)略數(shù)據(jù)分析”“業(yè)務(wù)數(shù)據(jù)分析” 是企業(yè) ...
2025-09-11Excel 數(shù)據(jù)聚類分析:從操作實踐到業(yè)務(wù)價值挖掘 在數(shù)據(jù)分析場景中,聚類分析作為 “無監(jiān)督分組” 的核心工具,能從雜亂數(shù)據(jù)中挖 ...
2025-09-10統(tǒng)計模型的核心目的:從數(shù)據(jù)解讀到?jīng)Q策支撐的價值導(dǎo)向 統(tǒng)計模型作為數(shù)據(jù)分析的核心工具,并非簡單的 “公式堆砌”,而是圍繞特定 ...
2025-09-10