二十九、深入Python中的collections模块
@Author: Runsen
collections模块是一个不用不知道,一用就上瘾的模块。这里主要介绍OrderedDict类、defaultdict类、Counter类、namedtuple类和deque类。
@[TOC]
collections
collections的常用类型有:
-
计数器(
Counter
) -
双向队列(
deque
) -
默认字典(
defaultdict
) -
有序字典(
OrderedDict
) -
可命名元组(
namedtuple
)
Counter
计数器(counter)以字典的形式返回序列中各个字符出现的次数,值为key,次数为value
Counter是对字典类型的补充,用于追踪值得出现次数 。
import collections
counter = collections.Counter("My name is Runsen")
print(counter)
输出如下
Counter({' ': 3, 'n': 3, 'e': 2, 's': 2, 'M': 1, 'y': 1, 'a': 1, 'm': 1, 'i': 1, 'R': 1, 'u': 1})
取得元素重复次数的值
print(counter[' '])
3
elements()取得计数器中的所有元素。
注:此处非所有元素集合,而是包含所有元素集合的迭代器.
counter = collections.Counter('abcabcabcdabcdef')
print(counter)
# 输出如下
Counter({'a': 4, 'b': 4, 'c': 4, 'd': 2, 'e': 1, 'f': 1})
print(counter.elements())
# 输出如下
<itertools.chain object at 0x0000025B1477BF98>
print(list(counter.elements()))
# 输出如下
['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'e', 'f']
将Counter按照value从大到小排列,获取前N个元素,需要使用函数most_common
# most_common(N)数量从大到小排列,获取前N个元素
print(counter.most_common(3))
# 输出如下
[('a', 4), ('b', 4), ('c', 4)]
sorted将Counter中的key进行排序,返回的是所有key的列表
# sorted()列出所有不同的元素并排序
print(sorted(counter))
# 输出如下
['a', 'b', 'c', 'd', 'e', 'f']
将Counter转换成字符串,字符串的join方法可以解决。注意不是原来的模样。
# 转换成字符串
print(''.join(counter.elements()))
# aaaabbbbccccddef
print(''.join(list(counter.elements())))
update()更新计数器,其实在原本的counter更新计数器,如果原来没有,则新建key,如果有value则加一
# update()更新计数器,
d = collections.Counter('a')
counter.update(d)
print(counter)
# 输出如下
Counter({'a': 5, 'b': 4, 'c': 4, 'd': 2, 'e': 1, 'f': 1})
update()更新计数器,那么subtract()相减计数器的values,即原来的计数器中的每一个元素的数量减去后添加的元素的数量
counter.subtract('abdabcabcg')
print(counter)
# 输出如下
Counter({'a': 2, 'c': 2, 'b': 1, 'd': 1, 'e': 1, 'f': 1, 'g': -1})
deque
deque支持从任意一端增加和删除元素。更为常用的两种结构,就是栈和队列。
deque的常见操作
#定义一个空的双向队列
d = collections.deque()
#从右端增加元素
d.extend("Runsen")
d.append("Maoli")
d.append("Python")
d.append("king")
#从左端增加元素
d.appendleft('left')
print(d)
# 输出如下 (注意:extend和append的区别)
deque(['left', 'R', 'u', 'n', 's', 'e', 'n', 'Maoli', 'Python', 'king'])
# reverse()反转队列
print(d.reverse())
d.reverse()
print(d)
# 输出如下
None
deque(['king', 'Python', 'Maoli', 'n', 'e', 's', 'n', 'u', 'R', 'left'])
d.reverse()
d.extend(['qq','ww','ee'])
print(d)
# deque(['left', 'R', 'u', 'n', 's', 'e', 'n', 'Maoli', 'Python', 'king', 'qq', 'ww', 'ee'])
# count()计数
print(d.count('R'))
# 输出如下
1
# clear()清空队列
d.clear()
print(d)
# 输出如下
deque([])
# index()取得元素下标
print(d.index('Maoli'))
# 输出如下
7
# insert()指定位置插入元素
d.insert(1,'Runsen')
print(d)
# deque(['left', 'Runsen',R', 'u', 'n', 's', 'e', 'n', 'Maoli', 'Python', 'king', 'qq', 'ww', 'ee'])
OrderedDict
使用dict时要保持Key的顺序,可以用OrderedDict。
from collections import OrderedDict
dic = OrderedDict()
dic['k1'] = 'v1'
dic['k2'] = 'v2'
dic['k3'] = 'v3'
print(dic)
# 输出如下
OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3')])
# 字典所有的键
print(dic.keys())
# 输出如下
odict_keys(['k1', 'k2', 'k3'])
# 字典所有值
print(dic.values())
# 输出如下
odict_values(['v1', 'v2', 'v3'])
# items() 方法以列表返回可遍历的(键, 值) 元组数组
print(dic.items())
# 输出如下
odict_items([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3')])
#pop()方法,删除指定的键值
dic.pop('k1')
print(dic)
# 输出如下
OrderedDict([('k2', 'v2'), ('k3', 'v3')])
#popitem()方法,默认删除字典最后一个元素
dic.popitem()
print(dic)
# 输出如下
OrderedDict([('k2', 'v2')])
# update()更新字典
dic.update({'k1':'v1111','k10':'v10'})
print(dic)
# 输出如下
OrderedDict([('k2', 'v2'), ('k1', 'v1111'), ('k10', 'v10')])
OrderedDict和字典操作完全相同,区别在于OrderedDict的Key会按照插入的顺序排列,不是Key本身排序
>>> from collections import OrderedDict
>>> d = dict([('a', 1), ('b', 2), ('c', 3)])
>>> d # dict的Key是无序的
{'a': 1, 'c': 3, 'b': 2}
>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> od # OrderedDict的Key是有序的
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
defaultdict
在使用字典的时候, 如果在使用不存在的key的时候发生KeyError这样的一个报错, 这时候就该defaultdict登场了。
defaultdict接受一个工厂函数作为参数来构造:dict =defaultdict( factory_function)
这个factory_function
可以是list、set、str等等,作用是当key不存在时,返回的是工厂函数的默认值,比如list对应[ ],str对应的是空字符串,set对应set( ),int对应0,如下举例:
from collections import defaultdict
dict1 = defaultdict(int)
dict2 = defaultdict(set)
dict3 = defaultdict(str)
dict4 = defaultdict(list)
dict1[2] ='two'
print(dict1[1])
print(dict2[1])
print(dict3[1])
print(dict4[1])
# 输出如下
0
set()
[]
defaultdict类接受类型名称作为初始化函数的参数,这样使得默认值的取值更加灵活。
s = 'mynameisrunsen'
d = collections.defaultdict(int)
for k in s:
d[k] += 1
print(d)
# 输出如下
defaultdict(<class 'int'>, {'m': 2, 'y': 1, 'n': 3, 'a': 1, 'e': 2, 'i': 1, 's': 2, 'r': 1, 'u': 1})
练习有如下值集合 [11,22,33,44,55,66,77,88,99,99]
。
下面将所有大于 55的值保存至字典的第一个key中,将小于 55 的值保存至第二个key的值中。
下面通过defaultdict默认字典对列表进行划分。
all_list = [11,22,33,44,55,66,77,88,99]
dic = collections.defaultdict(list)
for i in all_list:
if i > 55:
dic['k1'].append(i)
else:
dic['k2'].append(i)
print(dic)
# 输出如下
defaultdict(<class 'list'>, {'k2': [11, 22, 33, 44, 55], 'k1': [66, 77, 88, 99]})
也可以使用字典,具体代码如下。
all_list = [11,22,33,44,55,66,77,88,99]
dic = {}
for i in all_list:
if i > 55:
if "k1" in dic.keys():
dic['k1'].append(i)
else:
dic['k1'] = [i,]
else:
if "k2" in dic.keys():
dic['k2'].append(i)
else:
dic['k2'] = [i,]
print(dic)
# 输出如下
{'k2': [11, 22, 33, 44, 55], 'k1': [66, 77, 88, 99]}
namedtuple
namedtuple是用来创建一个自定义的tuple对象,并且规定了tuple元素的个数,并可以用属性而不是索引来引用tuple的某个元素。
使用命名元组的步骤:
# 将元组封装为一个类,可以通过字段名(属性名)来访问元组中的值
# 支持元组的所有操作
from collections import namedtuple
# 1、定义一个类
Runsen = namedtuple('Runsen', ['name','sex','age'])
# 2、创建对象
runsen = Runsen("Runsen", "帅男", 21)
# 3、获取命名元组的值
print(runsen[1]) # 支持元组的索引取值
print(runsen[-2:]) # 支持切片
print(runsen.name) # 支持通过字段名来取值
# _fields,获取命名元组的所有属性名
print(runsen._fields)
# _asdict方法,将元组转化为字典
print(runsen._asdict())
# 输出如下
帅男
('帅男', 21)
Runsen
('name', 'sex', 'age')
OrderedDict([('name', 'Runsen'), ('sex', '帅男'), ('age', 21)])
本文已收录 GitHub,传送门~ ,里面更有大厂面试完整考点,欢迎 Star。