12.14. collections模块¶
12.14.1. namedtuple¶
工厂函数,用于创建具有命名字段的元组子类
语法
namedtuple(typename, field_names, *, verbose=False, rename=False, module=None)
示例:
# 导入namedtuple
>>> from collections import namedtuple
# 创建一个用户类,拥有name,age,sex属性
>>> User = namedtuple("User", ["name","age","sex"])
>>> user1 = User("as","22","男")
>>> user1
User(name='as', age='22', sex='男')
# 通过属性进行访问
>>> user1.name
'as'
>>> user1.age
'22'
>>> user1.sex
'男'
# 拆包
>>> name, age, sex = user1
>>> name, age, sex
('as', '22', '男')
# namedtuple转换为字典
>>> user1._asdict()
OrderedDict([('name', 'as'), ('age', '22'), ('sex', '男')])
# 初始化时也可以传入一个字典
>>> user_info_dict = {"name":"ansheng","age":"20","sex":"男"}
>>> User(**user_info_dict)
User(name='ansheng', age='20', sex='男')
# 传入一个可迭代的
>>> user_info_list = ["ansheng","20","女"]
>>> User(*user_info_list)
User(name='ansheng', age='20', sex='女')
>>> user_info_list = ["ansheng","20"]
>>> User(*user_info_list,"男")
User(name='ansheng', age='20', sex='男')
# _make方法
>>> User._make(["as", 20, "男"])
User(name='as', age=20, sex='男')
12.14.2. deque¶
双端队列 示例
>>> from collections import deque
>>> users_deque = deque(["user1", "user2", "user3"], maxlen=10)
>>> users_deque.appendleft("user4")
>>> users_deque.append("user4")
>>> users_deque
deque(['user4', 'user1', 'user2', 'user3', 'user4'], maxlen=10)
使用 deque(maxlen=N) 构造函数会新建一个固定大小的队列。
当新的元素加入并且这个队列已满的时候, 最老的元素会自动被移除掉。
In [24]: q = deque(maxlen=3)
In [25]: q.append(1)
In [26]: q.append(2)
In [27]: q.append(3)
In [28]: q
Out[28]: deque([1, 2, 3])
In [29]: q.append(4)
In [30]: q
Out[30]: deque([2, 3, 4])
In [30]: q
Out[30]: deque([2, 3, 4])
In [31]: q.ap
q.append q.appendleft
In [31]: q.appendleft(9) #左边新增
In [32]: q
Out[32]: deque([9, 2, 3])
In [34]: q.appendleft(8) #左边新增
In [35]: q
Out[35]: deque([8, 9, 2])
In [36]: q.pop() #删除最末端的数,并返回数值
Out[36]: 2
In [37]: q
Out[37]: deque([8, 9])
In [38]: q.popleft() #删除最左边的数,并返回数值
Out[38]: 8
In [39]: q
Out[39]: deque([9])
问题¶
在迭代操作或者其他操作的时候,怎样只保留最后有限几个元素的历史记录?
from collections import deque
def search(lines, pattern, history=5):
previous_lines = deque(maxlen=history)
for line in lines:
if pattern in line:
yield line, previous_lines
previous_lines.append(line)
# Example use on a file
if __name__ == '__main__':
with open(r'../../cookbook/somefile.txt') as f:
for line, prevlines in search(f, 'python', 5):
for pline in prevlines:
print(pline, end='')
print(line, end='')
print('-' * 20)
12.14.3. ChainMap¶
dict-like class for creating a single view of multiple mappings
>>> from collections import ChainMap
>>> dict1 = {"a": "a", "b": "b"}
>>> dict2 = {"c": "c", "d": "d"}
>>> new_dict = ChainMap(dict1, dict2)
>>> new_dict.maps
[{'a': 'a', 'b': 'b'}, {'c': 'c', 'd': 'd'}]
>>> for key, value in new_dict.items():
... print(key, value)
...
a a
b b
d d
c c
a = {'x': 1, 'z': 3 }
b = {'y': 2, 'z': 4 }
from collections import ChainMap
c = ChainMap(a,b)
print(c['x']) # Outputs 1 (from a)
print(c['y']) # Outputs 2 (from b)
print(c['z']) # Outputs 3 (from a)
12.14.4. Counter¶
统计元素出现的次数 示例
>>> from collections import Counter
# 拥挤英文字母出现的次数
>>> letters = ["A", "A", "B", "C", "A", "H", "D", "B"]
>>> letters_counter = Counter(letters)
>>> letters_counter.update(["A", "A"])
>>> letters_counter
Counter({'A': 5, 'B': 2, 'C': 1, 'H': 1, 'D': 1})
# 出现最多的前2个元素
>>> letters_counter.most_common(2)
[('A', 5), ('B', 2)]
# 统计字符串
>>> Counter("asdasdsczasdasdasdasd")
Counter({'s': 7, 'a': 6, 'd': 6, 'c': 1, 'z': 1})
12.14.5. OrderedDict¶
dict subclass that remembers the order entries were added
>>> from collections import OrderedDict
>>> user_dict = OrderedDict()
>>> user_dict["name"] = "As"
>>> user_dict["age"] = 18
>>> user_dict["sex"] = "男"
>>> user_dict
OrderedDict([('name', 'As'), ('age', 18), ('sex', '男')])
# 把name移动到最后
>>> user_dict.move_to_end("name")
>>> user_dict
OrderedDict([('age', 18), ('sex', '男'), ('name', 'As')])
# 移除最后一个元素
>>> user_dict.popitem()
('name', 'As')
>>> user_dict
OrderedDict([('age', 18), ('sex', '男')])
12.14.6. defaultdict¶
当字典中Key不存在时,设置默认值
语法
defaultdict(FUNC_NAME)
接受一个函数名称
Code 统计列表中字母出现的次数
from collections import defaultdict
letters = ["A", "A", "B", "C", "A", "H", "D", "B"]
data_dict = defaultdict(int)
for letter in letters:
data_dict[letter] += 1
print(data_dict)
Output
defaultdict(<class 'int'>, {'A': 3, 'B': 2, 'C': 1, 'H': 1, 'D': 1})