collections 模块作用
包含双端队列 deque
、默认字典 defaultdict
、命名元组 namedtuple
、计数器 Counter
、Ordereddict
和 ChainMap
等重要模块。他们是增强版的高级数据结构。
1. tuple 功能
为了讲解 namedtuple
,所以先介绍 tuple
的功能,以便分析两者异同。
tuple 是一个不可变的元组,可迭代对象(内部实现了__iter__
,或者__getitem__
方法),可以进行拆包、tuple 的不可变性不是绝对的。
user_tuple = ('sqz', 23, 'Master')
name, age, degree = user_tuple # 这个过程称为拆包
name, *others = user_tuple # 进阶版的拆包
print(name, others)
# Output: sqz, [23, 'Master']
name_tuple = ('sqz', ['xiaoming', 'liangliang'])
name_tuple[1].append('xiaozhang') # 不可变性,不绝对
print(name_tuple)
# Output: ('sqz', ['xiaoming', 'liangliang', 'xiaozhang'])
tuple 和 list 相比的优势
immutable 的重要性:Python的性能优化(tuple
作为常量在编译时确定,加速脚本)、线程安全(线程无法对其进行修改)、可以作为 dict
的 key
值(可以进行哈希,而 list 不能)、 拆包特性。
2. namedtuple 功能
先来看简单的应用例子:
from collections import namedtuple
User = namedtuple('User', ['name', 'age', 'height', 'edu']) # 这里面相当于创建了一个简单的类
user = User(name='sqz', age=23, height=175)
user.edu = 'master' # 方便增加新的属性
print(user.name, user.age, user.height) # Output: sqz 23 175
# 另一种赋值方式
user_tuple = ('sqz', 23, 175)
user = User(*user_tuple, 'master')
print(user.name, user.age, user.height, user.edu) # Output: sqz 23 175 master
user_dict = {
"name":'sqz',
"age":23,
"height":175
}
user = User(**user_dict , edu = 'master')
# 使用内置函数_make()赋值,必须保持参数个数一致
user_dict = {
"name":'sqz',
"age":23,
"height":175
"edu" : "master"
}
user._make(user_dict)
# 使用内置函数_asdict()将namedtuple转化为一个OrderedDict
user_info_dict = user._asdict()
特点:
- 和创建一个简单类相比,形式更加简单,代码简洁。
- 节省空间,少了
class
中很多内置的函数和变量。 - 在对数据库进行操作时,如果需要给每一个条目增加属性,使用
namedtuple
作为数据结构,十分方便。
3. defaultdict 功能
defaultdict
是通过C语言实现的,性能特别的高。
defaultdict
的第一大作用:为新加入键值 key 分配默认的 value 值。实例如下:
from collections import defaultdict
default_dict = defaultdict(int) # 默认 value值为 0
users = ['sqz1', 'sqz2', 'sqz3', 'sqz2', 'sqz3'] # 统计列表中数据出现的次数
for user in users:
default_dict[user] += 1
defaultdict
的第二大作用:设计嵌套的字典结构,示例如下:
from collections import defaultdict
def gen_default(): # 可调用结构
return {
"name":""
"nums":0
}
default_dict = defaultdict(gen_default) # 参数传入可调用结构
default_dict['group1'] # 嵌套字典,group1的 key值为'name','nums'
4. deque 功能
C语言实现,效率高。双端队列,使用可迭代对象初始化,如 list、tuple、dict。代码示例:
from collections import deque
user_deque = deque(['sqz1', 'sqz2', 'sqz3'])
user_deque.appendleft('sqz8') # ['sqz8', 'sqz1', 'sqz2', 'sqz3'] 左侧添加数据
user_deque.clear() # 清空数据
copy()
函数实现浅拷贝:
from collections import deque
user_deque = deque(['sqz1', 'sqz2', ['sqz3']])
user_copy = user_deque.copy() # 不可变元素直接复制,可变元素直接指向(如 list)。
user_copy[0] = 'sqz100'
user_copy[2].append('sqzhaha')
print(user_deque) # deque(['sqz1', 'sqz2', ['sqz3', 'sqzhaha']])
print(user_copy) # deque(['sqz100', 'sqz2', ['sqz3', 'sqzhaha']])
Python 中同样提供了深拷贝的包:
import copy
from collections import deque
user_deque = deque(['sqz1', 'sqz2', ['sqz3']])
user_copy = copy.deepcopy(user_deque) # 深拷贝
user_copy[2].append('sqzhaha')
print(user_deque) # deque(['sqz1', 'sqz2', ['sqz3']])
print(user_copy) # deque(['sqz1', 'sqz2', ['sqz3', 'sqzhaha']])
extend()
函数将两个 deque
合并为一个:
from collections import deque
user_deque = deque(['sqz1', 'sqz2', ['sqz3']])
user_deque1 = deque(['haha'])
user_deque.extend(user_deque1) # 直接在 user_deque 上进行扩充,没有返回值
deque 是线程安全的,而 list 不是。
5. Counter
dict 的子类,用于统计元素数目,示例如下:
from collections import Counter
users = ['sqz1', 'sqz2', 'sqz4', 'sqz1', 'sqz2']
user_counter = Counter(users)
print(user_counter) # Counter({'sqz1':2, 'sqz2':2, 'sqz4':1}) 排序好的,次数最多的在前面
str_count = Counter('aanncddds')
str_count.update("bddc") # 更新统计,增加统计数据
str_count.most_common(2) # 取出前两个出现次数最多的元素
6. OrderedDict 功能
排好序的字典。继承自 dict,dict有的功能它都有。保持字典中元素的添加顺序
。在Python3中,dict 和 OrderedDict 都是有序的。而在Python2下, dict 无序,而OrderedDict有序。
from collections import OrderedDict
user_dict = OrderedDict()
user_dict['b'] = 'sqz2'
user_dict['a'] = 'sqz3'
user_dict['c'] = 'sqz1'
print(user_dict)
# Output: {'b':'sqz2', 'a':'sqz3', 'c':'sqz1'}
OrderedDict 中一些重要函数:popitem()
、move_to_end()
print(user_dict.popitem()) # ('c', 'sqz1')
print(user_dict.pop()) # 会报错,pop() 函数中应传递 key值。
print(user_dict.move_to_end('b')) # 输出None
print(user_dict) # 输出:{'a':'sqz3', 'c':'sqz1', 'b':'sqz2'}
7. ChainMap 功能
当想遍历多个可迭代对象时,将两个可迭代对象连接起来。在两个对象上加上迭代器,指向性的,并没有赋值结构和值。如下例:
from collections import ChainMap
user_dict1 = {'a':'sqz1', 'b':'sqz2'}
user_dict2 = {'c':'sqz2', 'd':'sqz3'}
new_dict = ChainMap(user_dict1, user_dict2)
for key, value in new_dict.items():
print(key, value)
# Output:
# a sqz1
# b sqz2
# c sqz2
# d sqz3
当两个地点中有重复 key值时,只能访问出现第一次的键值对。
一些重要函数:new_child()
、属性:maps
、
new_dict.new_child({'aa:'aa', 'bb':'bb'}) # add items
print(new_dict.maps) # [{'a':'sqz1', 'b':'sqz2'}, {'c':'sqz2', 'd':'sqz3'}, {'aa:'aa', 'bb':'bb'}] 以列表形式展现
new_dict.maps[0]['a'] = 'cherry' # 直接修改原数据