1. 程式人生 > >每天學點Python之collections

每天學點Python之collections

影響 初始 調用 print 額外 前端 如果 元素 mark

每天學點Python之collections

內容摘抄自:<python大法好>的每天學點Python之collections

collections模塊在內置數據類型(dict、list、set、tuple)的基礎上,提供了幾個額外的數據類型:ChainMap、Counter、deque、defaultdict、namedtuple和OrderedDict等。

ChainMap

ChainMap是python3的新特性,它用來將多個map組成一個新的單元(原來的map結構仍然存在,類似於這些map被存在了一個list之中),這比新建一個map再將其他map用update加進來快得多。通過ChainMap可以來模擬嵌套的情景,而且多用於模板之中。

ChainMap支持普通map的所有操作,下面主要展示一下它的特性:

# 新建ChainMap及它的結構
In[2]: from collections import ChainMap
In[3]: m1 = {color: red, user: guest}
In[4]: m2 = {name: drfish, age: 18}
In[5]: chainMap = ChainMap(m1, m2)
In[6]: print(chainMap.items())
ItemsView(ChainMap({user: guest, color
: red}, {age: 18, name: drfish})) # 獲取ChainMap中的元素 In[7]: print(chainMap.get(name)) drfish In[8]: print(chainMap.get(not)) None # 新增map In[9]: m3 = {data: 1-6} In[10]: chainMap = chainMap.new_child(m3) In[11]: print(chainMap.items()) ItemsView(ChainMap({data: 1-6}, {
user: guest, color: red}, {age: 18, name: drfish})) # parents屬性 In[12]: print(chainMap.parents) ChainMap({user: guest, color: red}, {age: 18, name: drfish}) In[13]: print(chainMap.parents.parents) ChainMap({age: 18, name: drfish}) In[14]: print(chainMap.parents.parents.parents) ChainMap({}) # maps屬性 In[15]: chainMap.maps Out[15]: [{data: 1-6}, {color: red, user: guest}, {age: 18, name: drfish}]

  • 可以傳入多個map來初始化ChainMap,如參數為空,會自動加入一個空的map
  • 獲取的key如果不存在,則返回None
  • 可以通過net_child()方法來新增map,新的map添加在前面
  • parents屬性返回除去第一個map後的ChainMap實例。

Counter

Counter是一個簡單的計數器,使用起來非常方便。

初始化

Counter的初始化支持多種形式

In[18]: from collections import Counter
In[19]: c = Counter()
In[20]: c = Counter(hello)
In[21]: c = Counter({a:3,b:19})
In[22]: c = Counter(cats=2,dogs=1)
In[23]: c
Out[23]: Counter({cats: 2, dogs: 1})

Counter對於不存在的元素會返回0,如果要刪除則需要用到del:

In[23]: c
Out[23]: Counter({cats: 2, dogs: 1})
In[24]: c[birds]
Out[24]: 0
In[25]: del c[cats]
In[26]: c
Out[26]: Counter({dogs: 1})

elements()方法會返回所有的元素,有幾個就返回幾個;而most_common(n)方法可以返回數量排前n的元素及其數目:

In[29]: c = Counter(a=4, b=2, c=0, d=-2)
In[30]: list(c.elements())
Out[30]: [a, a, a, a, b, b]
In[33]: c.most_common(1)
Out[33]: [(a, 3)]

不同的Counter之間還可以進行運算操作,subtract()方法進行減法後會影響調用方;&操作表示取兩個中數目小的一個(如果只在一個Counter中存在,則結果集中也沒有),|操作取數目大的。

In[46]: c = Counter(a=13, b=11)
In[47]: d = Counter(a=1, b=2)
In[48]: c.subtract(d)
In[49]: c
Out[49]: Counter({a: 12, b: 9})

In[51]: c+d
Out[51]: Counter({a: 13, b: 11})
In[52]: c-d
Out[52]: Counter({a: 11, b: 7})
In[54]: c&d
Out[54]: Counter({a: 1, b: 2})
In[55]: c|d
Out[55]: Counter({a: 12, b: 9})

註:進行運算操作時,如果數目結果為負的會被直接忽略

deque

deque就是一個雙端隊列,與list非常相似,不過可以同時在list的左邊增刪元素:

In[72]: dq = deque(abd)
In[73]: dq
Out[73]: deque([a, b, d])
In[74]: dq.append(1)
In[75]: dq.appendleft(-1)
In[76]: dq
Out[76]: deque([-1, a, b, d, 1])
In[77]: dq.popleft()
Out[77]: -1
In[78]: dq.extendleft("hello")
In[79]: dq
Out[79]: deque([o, l, l, e, h, a, b, d, 1])

註意extendleft(x)方法相當於先把x翻轉後在添加到列表前端。然後比較好用的是rotate方法,可以使隊列中的元素順序前移或者後移:

In[82]: dq=deque("12345")
In[83]: dq
Out[83]: deque([1, 2, 3, 4, 5])
In[84]: dq.rotate(2)
In[85]: dq
Out[85]: deque([4, 5, 1, 2, 3])
In[86]: dq.rotate(-4)
In[87]: dq
Out[87]: deque([3, 4, 5, 1, 2])

defaultdict

defaultdict在普通的dict之上添加了默認工廠,使得鍵不存在時會自動生成相應類型的值:

In[88]: from collections import defaultdict
In[89]: d = defaultdict(int)
In[90]: d[a]
Out[90]: 0
In[91]: d = defaultdict(dict)
In[92]: d[a]
Out[92]: {}

如果初始化時沒有加入默認工廠,則同樣會拋出KeyError錯誤:

In[93]: d = defaultdict()
In[94]: d[a]
Traceback (most recent call last):
    d[a]
KeyError: a

namedtuple

namedtuple是tuple的加強版本,最大的作用就是給tuple的每個位置的值設置了別名,增加了程序的可讀性:

In[95]: from collections import namedtuple
In[96]: Point = namedtuple("Point",[x,y])
In[97]: p = Point(1,2)
In[98]: p.x
Out[98]: 1
In[99]: p.y
Out[99]: 2

由於有了別名,相當於形成了一個字典,namedtuple可以轉化為下面要介紹的OrderedDict,同時也可以通過字典轉化而來:

In[100]: p._asdict()
Out[100]: OrderedDict([(x, 1), (y, 2)])
In[101]: d = {x:11,y:22}
In[102]: Point(**d)
Out[102]: Point(x=11, y=22)

namedtuple也提供了獲取所有域及修改相應值的方法:

In[108]: p
Out[108]: Point(x=1, y=2)
In[109]: p._fields
Out[109]: (x, y)
In[110]: p._replace(x=10)
Out[110]: Point(x=10, y=2)

OrderedDict

dict是無序,但有時我們希望字典是有序的,OrderedDict提供了這項服務,OrderedDict中的鍵值對是按照他們加入時的順序存儲的:

In[130]: fruit=((apple, 4), (banana, 3), (orange, 2), (pear, 1))

In[131]: d = dict(fruit)
In[132]: d
Out[132]: {apple: 4, banana: 3, orange: 2, pear: 1}
In[135]: d.popitem()
Out[135]: (apple, 4)
In[136]: d.popitem()
Out[136]: (orange, 2)
In[137]: d.popitem()
Out[137]: (banana, 3)
In[138]: d.popitem()
Out[138]: (pear, 1)

In[133]: od = OrderedDict(fruit)
In[134]: od
Out[134]: OrderedDict([(apple, 4), (banana, 3), (orange, 2), (pear, 1)])
In[139]: od.popitem()
Out[139]: (pear, 1)
In[140]: od.popitem()
Out[140]: (orange, 2)
In[141]: od.popitem()
Out[141]: (banana, 3)
In[142]: od.popitem()
Out[142]: (apple, 4)

註:OrderedDict中popitem(last=True)函數如果last設置為False,則先加入的先彈出

可以通過move_to_end(key, last=True)函數來改變鍵值對的位置,True時移到末尾,False移到開頭:

In[146]: od
Out[146]: OrderedDict([(apple, 4), (banana, 3), (orange, 2), (pear, 1)])
In[147]: od.move_to_end(apple)
In[148]: od
Out[148]: OrderedDict([(banana, 3), (orange, 2), (pear, 1), (apple, 4)])
In[149]: od.move_to_end(pear,False)
In[150]: od
Out[150]: OrderedDict([(pear, 1), (banana, 3), (orange, 2), (apple, 4)])

每天學點Python之collections