容器数据型态 collections
Python 的标准函数“ collections”是一个可以创建特别“容器数据型态”的函数库,所创建的容器可以用来替代 Python 一般内建的容器,例如 dict、list、set 和 tuple,熟练应用后不仅能提升程序码的可读性,更能提高程序执行的效率。
本篇使用的 Python 版本为 3.7.12,所有范例可使用 Google Colab 实作,不用安装任何软件 ( 参考:使用 Google Colab )
collections 的方法
下方列出 collections 模组常用的几个方法 ( 参考 Python 官方文件:collections ):
| 方法 | 说明 |
|---|---|
| namedtuple() | 创建一个自定义的 tuple 容器,并用“属性”的方式引用项目。 |
| deque | 创建一个类似 list 的对象,可以快速的在头尾加入或取出元素。 |
| ChainMap | 创建一个类似 dict 的对象,可以将多个 dict 串接成单一的对象。 |
| Counter | 创建一个 dict 计数器对象,用来计算可迭代对象中每个对象的数量。 |
| OrderedDict | 创建一个可以记录 key 顺序的 dict 对象。 |
| defaultdict | 创建一个可以使用可以默认值的 dict 对象。 |
import collections
要使用 collections 必须先 import collections 模组,或使用 from 的方式,单独 import 特定的类型。
import collections
from collections import namedtuple
namedtuple()
namedtuple() 可以创建一个自定义的 tuple 容器,并用“属性”的方式引用 tuple 的某个项目,不仅具备 tuple 的不可变性,又具有引用属性的弹性。
下方的例子使用 namedtuple 定义了一个 circle 对象,包含 x、y 和 r ( 中心点 xy 座标和半径 r ) 三个属性,使用时就可以像字典用法一般,读取指定的属性。
from collections import namedtuple
circle = namedtuple('Point', ['x', 'y', 'r'])
c = circle(10,20,50)
print(c) # Point(x=10, y=20, r=50)
print(c.x, c.y, c.r) # 10 20 50
print(c[0], c[1], c[2]) # 10 20 50
deque
虽然 Python 的 list 已经具有插入和删除元素的功能,但如果要处理“大量的”项目,就会产生效能不足的状况,然而使用 collections 将项目转换为类似 list 的 deque 对象,就能以高效率的方式处理 list 数据,当数据变成 deque 对象后,可使用下列的方法操作:
| 方法 | 参数 | 说明 |
|---|---|---|
| append() | x | 从最右边插入元素。 |
| appendleft() | x | 从最左边插入元素。 |
| extend() | iter | 从最右边插入可迭代元素。 |
| extendleft() | iter | 最左边插入可迭代元素 ( 注意 iter 插入的元素顺序是相反的 )。 |
| count() | x | 计算某个元素在 deque 对象中出现的次数。 |
| copy() | 浅拷贝 deque 对象。 | |
| index() | i | 取得某个位置的元素。 |
| insert() | i,x | 在某个位置插入元素。 |
| pop() | x | 取出并移除最右边的元素。 |
| popleft() | x | 取出并移除最左边的元素。 |
| remove() | x | 移除第一个找到的元素 |
| reverse() | 反转 deque 对象。 | |
| rotate() | i | 将元素往右移动多少格 ( 负值左移动 )。 |
| clear() | 清除 deque 对象。 |
from collections import deque
a = deque(['a','b','c','d','e']) # 建立 deque 物件
a.append('x')
a.append('y') # 在最右邊加入元素
print(a) # deque(['a', 'b', 'c', 'd', 'e', 'x', 'y'])
a.appendleft('x')
a.appendleft('y') # 在最左邊加入元素
print(a) # deque(['y', 'x', 'a', 'b', 'c', 'd', 'e', 'x', 'y'])
b = a.copy() # 淺拷貝
print(b) # deque(['y', 'x', 'a', 'b', 'c', 'd', 'e', 'x', 'y'])
print(a.count('x')) # 2,計算 x 出現的次數
a.extend(['m','n']) # 在最右邊加入 ['m','n']
print(a) # deque(['y', 'x', 'a', 'b', 'c', 'd', 'e', 'x', 'y', 'm', 'n'])
a.extendleft(['m','n']) # 在最左邊加入 ['m','n']
print(a) # deque(['n', 'm', 'y', 'x', 'a', 'b', 'c', 'd', 'e', 'x', 'y', 'm', 'n'])
print(a[5]) # b,取出第六個元素 ( 第一個為 0 )
a.insert(1,'k') # 在第二個位置插入 k
print(a) # deque(['n', 'k', 'm', 'y', 'x', 'a', 'b', 'c', 'd', 'e', 'x', 'y', 'm', 'n'])
a.pop() # 移除最右邊的元素
print(a) # deque(['n', 'k', 'm', 'y', 'x', 'a', 'b', 'c', 'd', 'e', 'x', 'y', 'm'])
a.popleft() # 移除最左邊的元素
print(a) # deque(['k', 'm', 'y', 'x', 'a', 'b', 'c', 'd', 'e', 'x', 'y', 'm'])
a.remove('x') # 移除第一個 x
print(a) # deque(['k', 'm', 'y', 'a', 'b', 'c', 'd', 'e', 'x', 'y', 'm'])
a.reverse() # 反轉
print(a) # deque(['m', 'y', 'x', 'e', 'd', 'c', 'b', 'a', 'y', 'm', 'k'])
a.rotate(5) # 往右邊移動五格
print(a) # deque(['b', 'a', 'y', 'm', 'k', 'm', 'y', 'x', 'e', 'd', 'c'])
a.clear() # 清空項目
print(a) # deque([])
ChainMap
ChainMap 可以创建一个类似 dict 的对象,可以将多个 dict 串接成单一的对象,串接后只要读取指定的属性,就能取得对应的内容 ( 属性相同的会取第一个属性 ),ChainMap 有下列几个方法:
| 方法 | 参数 | 说明| |
|---|---|---|
| maps | 一个可以更新的串列。 | |
| new_child | dict | 加入一个 dict 并返回一个新的 ChainMap 对象。 |
| parents | 返回一个新的、除了第一个项目以外的 ChainMap 对象。 |
from collections import ChainMap
a = {'x': 1, 'y': 2}
b = {'m': 3, 'n': 4}
c = {'i': 5, 'j': 6}
d = ChainMap(a, b, c) # 根據 a、b、c 建立一個 ChainMap 物件
print(d['m'], d['j']) # 3 6 讀取 ChainMap 物件中的 'm' 和 'j'
print(d.maps) # [{'x': 1, 'y': 2}, {'m': 3, 'n': 4}, {'i': 5, 'j': 6}]
print(d.maps[0]) # {'x': 1, 'y': 2}
e = d.new_child() # 加入一個空 dict 成為新的 ChainMap 物件
print(e) # ChainMap({}, {'x': 1, 'y': 2}, {'m': 3, 'n': 4}, {'i': 5, 'j': 6})
f = d.new_child({'z':100}) # 加入一個 'z':100} 成為新的 ChainMap 物件
print(f) # ChainMap({'z': 100}, {'x': 1, 'y': 2}, {'m': 3, 'n': 4}, {'i': 5, 'j': 6})
g = d.parents # 去除第一個項目,成為新的 ChainMap 物件
h = g.parents # 去除第一個項目,成為新的 ChainMap 物件
print(g) # ChainMap({'m': 3, 'n': 4}, {'i': 5, 'j': 6})
print(h) # ChainMap({'i': 5, 'j': 6})
Counter
Counter 可以创建一个 dict 计数器对象,用来计算可迭代对象中每个对象的数量,Counter 有下列几种方法:
| 方法 | 参数 | 说明| |
|---|---|---|
| elements() | 独立每个元素成为可迭代对象。 | |
| new_child | n | 取出数量前 n 多的项目。 |
| update | 将原本的数量加上新的数量。 | |
| subtract | 将原本的数量减去新的数量。 | |
| total | 计算全部数量的总和 ( 3.10 才支援 )。 |
from collections import Counter
t1 = 'hello world'
a = Counter(t1) # 創建一個計數器物件
print(a) # Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
b = list(a.elements()) # 取出每個項目成為串列
print(b) # ['h', 'e', 'l', 'l', 'l', 'o', 'o', ' ', 'w', 'r', 'd']
print(sorted(b)) # 排序 [' ', 'd', 'e', 'h', 'l', 'l', 'l', 'o', 'o', 'r', 'w']
c = a.most_common(3) # 取出前三多的項目
print(c) # [('l', 3), ('o', 2), ('h', 1)]
t2 = 'hello'
e = Counter(t2) # 建立新的計數器物件
a.update(e) # 加上新物件中的數量
print(a) # Counter({'l': 5, 'o': 3, 'h': 2, 'e': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
a.subtract(e) # 減去新物件中的數量
print(a) # Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
OrderedDict
通常建立一个 dict 对象时无法决定 key 的顺序,如果使用 OrderedDict 可以创建一个能记录 key 顺序 ( 先进先出 ) 的 dict 对象。
from collections import OrderedDict
a = OrderedDict()
a['x'] = 2
a['y'] = 3
a['z'] = 1
print(a) rderedDict([('x', 2), ('y', 3), ('z', 1)])
defaultdict
通常在使用 dict 字典时,如果引用的 key 不存在会出现错误消息,如果使用 defaultdict,就能创建一个可以使用可以默认值的 dict 对象。
from collections import defaultdict
a = 'hello world'
b = defaultdict(lambda: 0) # 創建一個空的使用預設值 0 的 dict 物件
for i in a:
b[i] += 1 # 依序將 a 的字母設為 key,如果有 key 就將數值增加 1
print(b) # faultdict(<function <lambda> at 0x10d7d5290>, {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
c = defaultdict(lambda: 'no') # 如果 key 不存在,就回傳 no
for i in a:
c[i] = i # 依序將 a 的字母設為 key 和值
print(c['h']) # h
print(c['a']) # no
微信扫码关注
抖音扫码关注