Python collection模块
? collections模塊主要實現了一些container datatypes(容器類型),作為builtin容器類型dict、list、set和tuple等的一個補充,包括以下新定義的容器類型:
| namedtuple() | factory function for creating tuple subclasses with named fields |
| deque | 雙端隊列,支持兩端快速出入隊列操作 |
| ChainMap | 將多個mapping 對象組合成一個mapping對象 |
| Counter | dict subclass,用來計數hashable對象 |
| OrderedDict | dict subclass that remembers the order entries were added |
| defaultdict | dict subclass,對dict中missing的key,調用一個指定的factory function |
| UserDict | wrapper around dictionary objects for easier dict subclassing |
| UserList | wrapper around list objects for easier list subclassing |
| UserString | wrapper around string objects for easier string subclassing |
chainMap
? chainMap(*maps)用于連接多個mapping對象稱為一個mapping,通常其速度快于使用字典的update方法連接。其構造方法為collections.ChainMap(*maps),當不傳入參數時,ChainMap則會產生一個空dict;ChainMap底層用list存儲mapping對象,并且可以通過.maps屬性對mapping對象進行修改,對mapping對象的修改能夠即時反應到ChainMap對象;查找會依次搜索每一個mapping對象,而修改、刪除、新增只會在第一個mapping對象上進行操作。
? ChainMap對象除了支持所有的mapping對象方法,還有以下幾個特有的屬性、方法:
-
maps
如上所述,返回ChainMap所包裝的mapping對象所組成的list,該list至少包含一個mapping對象;
-
new_child(m=None)
創建child context,等價于ChainMap(m, *d.maps),當m為None時,等價于ChainMap({}, *d.maps)
-
parents
返回parent context,即返回除了第一個mapping對象之外的所有mapping對象組成的ChainMap對象
舉個簡單的例子:
>>> baseline = {'music': 'bach', 'art': 'rembrandt'} >>> adjustments = {'art': 'van gogh', 'opera': 'carmen'} >>> from collections import ChainMap >>> a = ChainMap(adjustments, baseline) >>> a['art'] 'van gogh'
Counter
? Counter([iterable-or-mapping])類用于快速、方便的計數,使用頻率很高的一個功能,它繼承于dict,用于計數可哈希的對象,計數的數值可以是正整數、負整數和零,實例化方法有以下幾種:
>>> c = Counter() # a new, empty counter >>> c = Counter('gallahad') # a new counter from an iterable >>> c = Counter({'red': 4, 'blue': 2}) # a new counter from a mapping >>> c = Counter(cats=4, dogs=8) # a new counter from keyword args? Counter和dict不同之處在于如果Counter檢索一個不存在的key時不會拋出KeyError,而是返回0:
>>> c = Counter(['eggs', 'ham']) >>> c['bacon'] # count of a missing element is zero 0 >>> del c['eggs']? 除了支持父類dict大部分的方法(不支持fromkeys(iterable)以及update([*iterable-or-mapping*])略有不同),還包括以下幾個:
-
elements()
返回一個iterator對象,每個元素重復其計數數值的次數(如果計數數值小于1,就忽略它)
>>> c = Counter(a=4, b=2, c=-1, d=-2) >>> c.elements() >>> list(c.elements()) # If an element’s count is less than one, elements() will ignore it.<itertools.chain at 0x112f1be10> ['a', 'a', 'a', 'a', 'b', 'b'] -
most_common(n)
返回計數最大的n個元素
>>> c.most_common(2) c.most_common(2)>>> c.most_common()[:-3:-1] # c.most_common()[:-n-1:-1] n least common elements -
subtract()
執行計數減法操作,加法可以使用update()方法
>>> c.subtract(Counter(a=1, b=2, c=3, d=4)) >>> c >>> c.update({'a':3}) # update([iterable-or-mapping]), 添加式的update >>> cCounter({'a': 3, 'b': 0, 'c': -4, 'd': -6}) Counter({'a': 6, 'b': 0, 'c': -4, 'd': -6})Counter還支持一些數學運算符,進行簡便的運算:
>>> c = Counter(a=-3, b=5, c=4) >>> d = Counter(a=-1, b=2, c=0) >>> c + d # add two counters together: c[x] + d[x] (keeping only positive counts) Counter({'b': 7, 'c': 4}) >>> c - d # subtract (keeping only positive counts) Counter({'b': 3, 'c': 4}) >>> c & d # intersection: min(c[x], d[x]) (keeping only positive counts) Counter({'b': 2}) >>> c | d # union: max(c[x], d[x]) (keeping only positive counts) Counter({'b': 5, 'c': 4})# 特殊的是,還提供兩個shortcuts來表示空的Counter()加上或減去Counter對象 >>> c = Counter(a=2, b=-4) >>> +c # 相當于 Counter() + c Counter({'a': 2}) >>> -c # 相當于 Counter() - c Counter({'b': 4})
deque
? collections.deque([iterable[, maxlen]]),以一個iterable對象作為參數進行初始化,得到一個雙端隊列。雙端隊列支持從任一側線程安全,內存高效的append和pop操作,并且復雜度為時間O(1)。如果未指定maxlen或為None,則雙端隊列的長度可以增長到任意大小;反之,雙端隊列會限制為指定的最大長度。一旦限定長度的雙端隊列達到最大長度時,若再插入新的item,則隊列另一端會自動丟棄相應數量的item。
-
方法和屬性
- append(x)、appendleft(x) 插入元素,前者插到隊列右邊,后者插入到左邊
- extend(iterable)、extendleft(iterable) 插入多個元素,前者插到隊列右邊,后者插入到左邊
- pop()、popleft() 去除并返回最左(右)邊的元素
- clear() 清空隊列
- copy() 隊列淺拷貝(同copy.copy(d)),深拷貝使用copy.deepcopy(d)
- count(x) 計數隊列中與x大小相等的元素個數
- index(x[, start[, stop]]) 在[start, stop)范圍內查找與x相等的第一個元素的index,如果沒找到拋出ValueErrorc錯誤
- insert(i, x) 在位置i插入x,若i位置超出隊列指定的最大長度,引發IndexError
- remove(value) 去除第一個與value相等的元素,若不存在引發ValueError
- reverse() in place的反轉隊列元素
- rotate(n=1) n> 0, 隊列向右移n步,反之向左移
- maxlen,這是一個只讀屬性
除了以上的屬性方法, deques 還支持iteration, pickling, len(d), reversed(d), copy.copy(d), copy.deepcopy(d), in 操作符 以及索引操作,如d[-1]. 索引隊列兩邊的元素復雜度都是O(1),當索引獲取中間的元素復雜度會是O(n), 因此涉及大量中間元素索引操作的場景應該使用list。
-
應用舉例
比如獲取一個文件的后N行可以采用以下方式:
def tail(filename, n=10):with open(filename) as f:return deque(f, n)
defaultdict
? 關于defaultdict,我們可以先看一下dict中一個類似功能的函數setdefault(k, d=None):
d = {} s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]for k, v in s:d.setdefault(k, []).append(v)sorted(d.items()) [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]? 在上述代碼中,setdefault(k, d=[])一句話相當于做了兩件事情:一是獲取key為k的的value,二是若該key不存在則設置其值為[]。即,d.get(k, [])以及如果key不存在就設置d[k] = []?,F在再回到defaultdict,defaultdict([default_factory[, ...]]),構造方法中default_factory默認是None,defaultdict是dict的一個subclass,它重寫了一個__miss__方法以及擁有一個default_factory屬性。
-
__miss__(key)
-
該方法在當key不存在時才會且僅被__getitem__()調用,所以當使用dict.get()方法獲取一個不存在的鍵值時,返回結果為None,而不是使用default_factory;
-
當default_factory為None時,索引一個不存在的key會引發KeyError異常;
-
當default_factory不為None時,索引一個不存在的key則使用default_factory進行初始化并返回值
>>> from collections import defaultdict>>> d2 = defaultdict(int ,a=1, b=2) >>> d2['c'] 0>>> d2 = defaultdict(int ,a=1, b=2) >>> d2.get('c') None >>> d2 defaultdict(int, {'a': 1, 'b': 2})>>> d1 = defaultdict(a=1, b=2) >>> d1['c'] KeyError: 'c'
-
-
default_factory
該屬性在上述__miss__()函數中使用,由構造函數中的default_factory初始化,默認為None
? 因此,上述例子可以使用defaultdict來實現如下:
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)] d = defaultdict(list) for k, v in s:d[k].append(v)sorted(d.items()) [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
namedtuple
? namedtuple用來構造帶字段名的元組。namedtuple的實例和普通元組消耗的內存一樣多,因為字段名都被存在對應的類里面。這個類跟普通的對象實例比起來也要小一些,因為 Python 不會用 __dict__ 來存放這些實例的屬性。它們可以在使用常規tuple的任何地方使用,并且它們還具有按名稱(tuple只能按index)訪問字段的能力。其構造函數為:collections.namedtuple(typename, field_names,*, rename=False, defaults=None, module=None),簡單例子如下:
>>> # Basic example >>> Point = namedtuple('Point', ['x', 'y']) >>> p = Point(11, y=22) # instantiate with positional or keyword arguments >>> p[0] + p[1] # indexable like the plain tuple (11, 22) 33 >>> x, y = p # unpack like a regular tuple >>> x, y (11, 22) >>> p.x + p.y # fields also accessible by name 33 >>> p # readable __repr__ with a name=value style Point(x=11, y=22)OrderedDict
? OrderedDict和一般的dict類似,但是還具有記憶字典中存儲的key的插入順序。但是現在OrderDict可能用處不大了,因為從Python 3.7開始,一般的dict也具有這個特性。但是,dict和OrderedDict依舊有些區別:
- 對于常規dict,最重要的高效的mapping operations,而Track 插入順序是次要的;
- 對于OrderedDict,最重要的是排序操作,而空間效率、迭代效率以及更新字典的性能是次要的;
- OrderedDict可以處理頻繁的需要重排的操作,適合于Track最近的操作;
- 判斷兩個OrderedDict是否相等同時要求順序也相同;
- OrderedDict的popitem(last=True)中可以通過last參數控制pop哪一端的元素;
- OrderedDict的move_to_end(key, last=True)可以高效的將元素移至末尾;
- 直到Python3.8,dict沒有__reversed__()方法;
UserDict & UserList & UserString
? UserDict & UserList & UserString分別是dict、list、str的一個wrapper,在實際應用中,已經很少使用到它們了,因為我們可以直接方便的繼承它們,自定義對應的子類,稍微了解一下即可,下面給出一個簡單的例子:
總結
以上是生活随笔為你收集整理的Python collection模块的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python函数式编程之functool
- 下一篇: R语言入门4---R语言流程控制