1. 程式人生 > 程式設計 >詳解Python 中的容器 collections

詳解Python 中的容器 collections

寫在之前

我們都知道 Python 中內建了許多標準的資料結構,比如列表,元組,字典等。與此同時標準庫還提供了一些額外的資料結構,我們可以基於它們建立所需的新資料結構。

Python 附帶了一個「容器」模組 collections,它包含了很多的容器資料型別,今天我們來討論其中幾個常用的容器資料型別,掌握了這幾個可以減少我們重複造輪子所帶來的煩擾。

namedtuple

相信你已經熟悉了元組。一個元組相當於一個不可變的列表,你可以儲存一個數據的序列。這裡要說的 namedtuple(命名元組)和元組非常像,它們都不能修改自己的資料。說完了像,那麼它們有哪些地方不像呢?

作為元組,為了獲取其中的資料,我們需要使用整數作為索引:

>>> people = ('Rocky','python')
>>> print(people[0])
Rocky

而 namedtuple 把元組變成了一個針對簡單任務的容器,我們不必使用整數索引來訪問 namedtuple 的資料,反而可以像用字典一樣訪問 namedtuple。

>>> from collections import namedtuple
>>> people = namedtuple('people','name age like')
>>> Rocky = people(name = 'rocky',age = 23,like = 'python')
>>> print(Rocky)
people(name='rocky',age=23,like='python')
>>> print(Rocky.name)
rocky

一個 namedtuple 有兩個必須的引數:元組名稱和欄位名稱。在上面的程式碼中,我們的元組名稱是 people,欄位名稱是 name,age,like。nametuple 讓元組變的更加易讀,很容易理解程式碼是做什麼的,同樣我們也不用使用整數索引來訪問一個命名元組(上面程式碼我們用 name 訪問了 namedtuple 中的資料),這讓我們的程式碼更加容易維護。

但是你一定要記住的是,雖然它的用法很爽,但它還是一個元組!所以屬性值在 namedtuple 中是不可變的。

我們在上面說過可以像用字典一樣訪問 namedtuple,那麼當然也可以把它轉為字典,具體操作如下所示:

>>> from collections import namedtuple
>>> people = namedtuple('people',like = 'python')
>>> print(Rocky._asdict())
OrderedDict([('name','rocky'),('age',23),('like','python')])

defaultdict

我之前在使用字典的時候相當隨意,只是隨便 dict 一下就好了,然而這樣使用存在一個問題:當使用的 key 不存在的時候會報 KeyError,而 defaultdict 就比較厲害了,我們完全不需要檢查 key 是否存在,所以我們能像下面這樣做的隨心所欲:

from collections import defaultdict

languages = (
  ('rocky','python'),('snow','c'),('leey','java'),('rocky','c++'),'c#')
)

favourite = defaultdict(list)

for name,language in languages:
  favourite[name].append(language)

print(favourite)

輸出如下所示:

defaultdict(<type 'list'>,{'leey': ['java','c#'],'rocky': ['python','c++'],'snow': ['c']})

然後我們再回到“鍵不存在,會觸發 KeyError 異常”這個問題上來,我們先來看 dict 觸發 KeyError 的例子:

my_dict = {}
my_dict['name']['like'] = 'python'

輸出如下:

KeyError: 'name'

defaultdict 則用了一個非常巧妙的方式繞過了這個問題,請看下面的操作:

import collections
language = lambda : collections.defaultdict(language)
my_dict = language()
my_dict['name']['like'] = 'python'

執行一下顯示正常,我們可以用 json.dumps 打印出 my_dict 的內容:

import json
print(json.dumps(my_dict))

執行結果如下:

{"name": {"like": "python"}}

Counter

Counter 是一個計數器,它可以幫助我們針對某項資料進行計數,比如可以用它來統計每個人擅長的程式語言:

from collections import Counter

languages = (
('rocky','c#')
)

cnt = Counter(name for name,language in languages)
print(cnt)

執行結果如下所示:

Counter({'leey': 2,'rocky': 2,'snow': 1})

當然我們也可以用它來統計一個檔案,比如:

from collections import Counter

with open('test.txt','rb') as f:
line_cnt = Counter(f)

print(line_cnt)

deque

deque 提供了一個雙端佇列,我們可以在首尾兩端新增或者刪除元素

想要使用 deque,首先我們要從 collections 中匯入 deque 模組,然後建立一個 deque 物件,它的用法就像我們前面學過的 list 一樣,並且提供了類似的方法,具體如下所示:

from collections import deque

deq = deque()
deq.append(1)
deq.append(2)
deq.append(3)
print(deq)
print(len(deq))
print(deq[0])
print(deq[-1])

輸出結果如下:

deque([1,2,3])
3
1
3

我們可以從兩端取出資料:

from collections import deque

deq = deque(range(5))
print('len(deq) == {}'.format(len(deq)))
deq.popleft()
deq.pop()
print(deq)

輸出的結果如下所示:

len(deq) == 5
deq == deque([1,3])

我們也可以對這個列表的大小進行限制,當超出我們的限制的時候,資料會從另一端被 pop 出去,具體我們來看下面的操作:

from collections import deque

deq = deque(maxlen=3)
deq.append(1)
deq.append(2)
deq.append(3)
print(deq)
deq.append(4)
print (deq)

輸出的結果如下:

deque([1,3],maxlen=3)
deque([2,3,4],maxlen=3)

當超出 maxlen 的值時,最左邊的資料將從佇列中刪除。

當然我們還可以從任意一端擴充套件這個雙端佇列中的資料:

from collections import deque

deq = deque([1,3])
deq.extendleft([0])
deq.extend([4,5,6])
print(deq)

輸出的結果如下所示:

deque([0,1,4,6])

以上就是詳解Python 中的容器 collections的詳細內容,更多關於python collections的資料請關注我們其它相關文章!