Python標準庫--collections模組(1)

2020-08-12 19:24:03

collections模組簡介

collections是Python標準庫裡有關數據型別的模組,裏面包含了一些實用的數據型別,在某些情況下作爲Python標準內建容器 (dict , list , set , 和 tuple )的替代選擇。

namedtuple() 命名元組的工廠函數

Python官方文件上是這樣說的:"命名元組賦予每個位置一個含義,提供可讀性和自文件性。它們可以用於任何普通元組,並新增了通過名字獲取值的能力,通過索引值也是可以的。「我是這樣理解的:它可以構建一個有名字的類,而且爲元組中的元素新增了更易懂的"名字」(或者說是對元素的簡單描述),這樣就可以用"名字"取值

如果元組內的元素很多,比如記錄一個人的身高,年齡,家庭住址,電話號碼…等等,只靠索引存取這些資訊是很麻煩的,這就凸顯出了"名字"的重要性。

from collections import namedtuple

City = namedtuple('City', 'name country')  #注1
beijing = City('Beijing', 'China')
print(beijing)  #City(name='Beijing', country='China')
print(beijing.name)  #通過"名字"獲取對應的值
print(beijing.country)
print(beijing[0])  #同樣支援用索引存取

注1.建立了一個類名是"City"的類,其中"name"和"country"是"名字","名字"可以是數個字串組成的可迭代型別(比如list),還可以是用空格分開的字串。

下面 下麪介紹一些常用的功能

from collections import namedtuple

Point = namedtuple('Point', ['x', 'y'])

print(Point._fields)  #_fields方法會返回一個包含"Point"類裡所有"名字"的元組 ('x', 'y')

p = [1,2]
print(Point._make(p))  #_make()接受一個可迭代物件建立新的命名元組

p = Point(1,2)
print(p._asdict())  #返回一個OrderedDict(這個數據型別以後再談),它能友好地呈現出元組裏的資訊

print(p._replace(x=2))  #返回一個新的命名元組範例,並將指定"名字"的值替換爲新的值

print(p)  #_replace()返回的是新的命名元組範例,所以p不會改變

p2 = {'x':2, 'y':3}
print(Point(**p2))  #將字典轉化爲命名元組

Counter(計數器)

Counter是dict的子類,可以給可雜湊物件(文末有解釋)計數
廢話不多說,直接上例子:

from collections import Counter
a = Counter('aaabbcdddd')  #統計'aaabbcdddd'(可迭代物件)裡字母出現的次數並建立對應的計數器(按次數大小排列)
print(a)

b = Counter()  #空的計數器
print(b)

c = Counter({'a': 3, 'b': 2, 'c': 3, 'd': 4})  #根據字典建立計數器
print(c)

d = Counter(a=3, b=2, c=1, d=4)  #根據鍵值建立
print(d)

e = Counter(['a', 'a', 'b'])  #也可以換成其他可迭代物件
print(e['a'])  #統計列表中'a'出現的次數
print(e['c'])  #如果沒有相應的鍵就返回零

下面 下麪介紹一些常用的功能

from collections import Counter

# elements()方法會返回一個迭代器
a = Counter(a=2, b=1, c=0, d=-1)  # elements()函數會忽略計數值小於1的元素
print(sorted(f.elements()))  # 迭代器不能直接列印,需要先用sorted()函數新建一個列表

# most_common([n])返回一個包含n個最常見的元素及出現次數的列表
b = Counter('aaabbcdddd')
print(g.most_common(2))  # 結果:[('d', 4), ('a', 3)]
print(g.most_common())  # 如果不傳參或傳"None",將返回計數器中的所有元素
print(g.most_common(None))

#subtract減去元素
e = Counter(a=4, b=1, c=0, d=-1)
f = Counter(a=2, b=1, c=2, d=0)
e.subtract(f)  #這裏既可以減去可迭代物件(如字串,列表)也可以是對映物件(如字典)
print(e)
e.subtract('aaa')
print(e)  #輸入和輸出都可以是0或者負數

關於可雜湊物件的介紹不多,《流暢的Python》裡是這樣說的(選自Python詞彙表):

如果一個物件是可雜湊的,那麼在這個物件的生命週期中,他的雜湊值是不會變的,而且這個物件需要實現__hash__()方法。另外還要有__eq__()方法,這樣才能 纔能和其他鍵作比較。如果兩個可雜湊物件是相等的,那麼他們的雜湊值一定是一樣的

簡單說可雜湊物件就是能被對映成數位的物件

「可雜湊」,"對映"會牽扯到一種數據結構:雜湊表(《演算法圖解》第五章和《流暢的Python》第三章中對雜湊表都有一定介紹,讀者可以用微信讀書瞭解這種數據結構)

在理解了雜湊表之後,可雜湊物件就不難理解了

下面 下麪看幾個例子

a = 1
print(hash(a))

s = 'a'
print(hash(s))

t1 = (1, 2, 3)
t2 = (1, [2, 3])
t3 = (1, frozenset([2, 3]))
print(hash(t1))
print(hash(t2))
print(hash(t3))

l = [1,2]
print(hash(l))  #list是不可雜湊的,所以會拋出異常:TypeError: unhashable type: 'list'

b = 1
print(hash(a)==hash(b))

在以上的例子中,變數a,s,t1和t3都是可雜湊物件(都實現了__hash__()方法)
最後一個例子證明了"如果兩個可雜湊物件是相等的,那麼他們的雜湊值一定是一樣的"這句話

總結一下可雜湊物件:
1.str(s),bytes,和數值型別(a)
2.frozenset,因爲frozenset只能容納可雜湊型別
3.在元組裏的所有元素都是可雜湊型別的情況下,它纔是可雜湊的

本文的參考資料:
Python官方文件
其他大佬的部落格
其他大佬的部落格
《流暢的Python》
《演算法圖解》

本文的程式碼:
碼雲

這是我小白第一篇部落格,歡迎大家在評論區分享自己的理解吐槽