collections是Python標準庫裡有關數據型別的模組,裏面包含了一些實用的數據型別,在某些情況下作爲Python標準內建容器 (dict , list , set , 和 tuple )的替代選擇。
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是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》
《演算法圖解》
本文的程式碼:
碼雲
這是我小白的第一篇部落格,歡迎大家在評論區分享自己的理解吐槽