Python标准库中collections介绍

collections—容器数据类型

collections模块提供了除list、dict、和tuple之外,还有我们接下来介绍的Counter、defaultdict、deque、namedtuple、OrderDict等额外数据类型

Counter对字符串、列表、元组、字典进行计数,返回一个字典类型的数据
defaultdict字典的子类,提供了一个工厂函数,为字典查询提供一个默认值
deque类似列表的容器,实现了在两端快速添加(append)和弹出(pop)
namedtuple()创建命名元组子类的工厂函数
OrderedDict()字典的子类,保存了他们被添加的顺序

一、Counter对象

1、实现对字符串、列表、元组等数据的简单计数

from collections import Counter

print(Counter('aabbbccc'))
print(Counter(cats=4, dogs=8))
print(Counter([1,1,2,2,2,3,3,3,3]))
print(Counter(('a','a','b','b','b',1,1,2,2,2)))

输出结果:
Counter({‘b’: 3, ‘c’: 3, ‘a’: 2})
Counter({‘dogs’: 8, ‘cats’: 4})
Counter({3: 4, 2: 3, 1: 2})
Counter({‘b’: 3, 2: 3, ‘a’: 2, 1: 2})

2、对计数值加、减、交、并运算

可以直接进行计数结果的加减,还可以取交集和并集返回相应计数的最小或最大值。

from collections import Counter

a=Counter(c=3,d=6)
b=Counter(c=5,d=1)
print(a+b)
print(a&b)
print(a|b)

输出结果:

Counter({'c': 8, 'd': 7})
Counter({'c': 3, 'd': 1})
Counter({'d': 6, 'c': 5})

3、most_common() 函数

most_common(n)返回出现次数从大到小前n个元素,若n大于元素个数,则全部元素返回。

print(Counter('aabbbcccc').most_common(2))

输出结果:

[('c', 4), ('b', 3)]

4、elements() 函数

返回所有元素,出现一次返回一次,一般用于循环索引使用,单个调用不会有结果。如果元素计数值小于1会被忽略。

from collections import Counter
import numpy as np

x = np.random.randint(1,10,5) #取1~10之间的随机整数,取5个(自己设定)
counts1 = Counter(x)
for i in counts1.elements():
    print(i)
    
a=Counter(c=3,d=4,e=0,f=-5)
print(sorted(a.elements()))

输出结果:

7
6
1
1
8

['c', 'c', 'c', 'd', 'd', 'd', 'd']

5、subtract(iterable / mapping)函数和键的删除

元素从一个迭代器(或计数器)中减去,像dic.update()一样,但减去计数而不是替换他们,但如果减去本身没有的元素,也可以计算,本身默认计数为0。如下面元素的“它”。

a1 = Counter(=4,=5,=2)
a2 = Counter(=2,=3,=5,它=6)
a1.subtract(a2)
print(a1)
del a1["我"] #键的删除
print(a1)

输出结果:

Counter({'我': 2, '你': 2, '他': -3, '它': -6})
Counter({'你': 2, '他': -3, '它': -6})

二、defaultdict对象

1、使用目的和方法

当我们用python访问字典中不存在的键会报错,而使用defaultdict会使字典里的key不存在但被查找时,返回一个默认值。
dict = defaultdict( factory_function)接受一个工厂函数做参数,就是给初始key生成一个默认值,可以是list、set、int、str等,分别对应默认值[ ]、set()、0、空字符串。

dict1 = defaultdict(int)
dict2 = defaultdict(set)
dict3 = defaultdict(str)
dict4 = defaultdict(list)
print(dict1[1])
print(dict2[1])
print(dict3[1])
print(dict4[1])

输出结果:

0
set()

[]

2、defaultdict(list) 和 setdefault()的使用和对比

这里先介绍一下setdefault(key[,default])方法,它使用指定的键返回项目的值。如果字典中存在相应的键则默认参数无效,否则该参数作为键的值,默认default为None。
示例

#defaultdict()
from collections import defaultdict
import time
a = [('red',1),('green',2),('blue',3),('red',2),('blue',5)]
d = defaultdict(list)
for k,v in a:
    d[k].append(v)
print(type(d))
print(sorted(d.items()))
print(time.time())

输出结果:

<class 'collections.defaultdict'>
[('blue', [3, 5]), ('green', [2]), ('red', [1, 2])]
1639212236.2430627
#setdefault()
import time
a = [('red',1),('green',2),('blue',3),('red',2),('blue',5)]
d1 = {}
for k,v in a:
    d1.setdefault(k,[]).append(v)
print(type(d1))
print(sorted(d1.items()))
print(time.time())

输出结果:

<class 'dict'>
[('blue', [3, 5]), ('green', [2]), ('red', [1, 2])]
1639212714.7426565

可以看出,defaultdict(list)使用起来效果和运用dict.setdefault()比较相似,近乎等价,但defauldict()相对较快且简单。

3、defaultdict(set)

集合(set)是一个无序的不重复元素序列。可以使用大括号{}或者set()函数创建集合。但是创建一个空集合必须用set()而不是{ },因为 { }是用来创建一个空字典。

from collections import defaultdict
a1 = [('red',1),('green',2),('blue',5),('red',2),('blue',5)]
d1 = defaultdict(set)
for k,v in a1:
    d1[k].add(v)
print(d1)
print(d1.items()) #这里因为重复两个blue都是5,set()起作用
a2 = [('red',1),('green',2),('blue',3),('red',2),('blue',5)]
d2 = defaultdict(set)
for k,v in a2:
    d2[k].add(v)
print(d2.items())

输出结果:

defaultdict(<class 'set'>, {'red': {1, 2}, 'green': {2}, 'blue': {5}})
dict_items([('red', {1, 2}), ('green', {2}), ('blue', {5})])    
dict_items([('red', {1, 2}), ('green', {2}), ('blue', {3, 5})])

三、deque对象

deque与list的容器类似,都支持快速增加或删除元素,但不同的是deque的序列两端都可以进行操作,并且deque在出队(pop)和入队(append)时的时间复杂度是O(1),而list时间复杂度是O(n),相比更加高效。

1、使用目的和方法

deque([iterable[, maxlen]])
iterable :创建的可迭代数据,默认新队列为空。
maxlen:限定指定最大长度, 没有指定或者是 None ,deques 可以增长到任意长度。

2、append(x) 和 appendleft(x)方法

在队列左侧和右侧增加元素数据。

from collections import deque
a = deque('abandon')
b = deque([1,2,3,4,5,6,7],maxlen=4) #限制长度,先进先出,所以保留后面元素
a.append('A')
a.appendleft('B')
print(a)
print(b)

输出结果:

deque(['B', 'a', 'b', 'a', 'n', 'd', 'o', 'n', 'A'])
deque([4, 5, 6, 7], maxlen=4)

2、reversed() 和 copy.copy()方法

reversed()进行逆序排列。copy.copy()复制一个相同队列,而不能直接赋值。

from collections import deque
import copy
a = deque('abandon')
c = copy.copy(a)
print(a)
print(list(reversed(a)))
print(c)
[ 'n', 'o', 'd', 'n', 'a', 'b', 'a']
deque(['a', 'b', 'a', 'n', 'd', 'o', 'n'])

3、remove()、pop() 和 popleft()方法

from collections import deque
x = deque([1,2,3,4,5,6])
x.remove(2)         #移除对应的值,没有会引起错误
x.pop()             #移除最右边的元素
x.popleft()         #移除最左边的元素
print(x)

输出结果:

deque([3, 4, 5])

4、rotate(n)方法

相当于将元素头尾连接成环,顺时针、逆时针旋转。如果n为正,向右循环移动 n 步。 如果 n 是负数,就向左循环。
若deque不是空的,向右循环移动一步就等价于 d.appendleft(d.pop()) , 向左循环一步就等价于 d.append(d.popleft()) 。

from collections import deque
import copy
y = deque([1,2,3,4,5,6])
y.rotate(2)
print(y)
z = copy.copy(y)
z.rotate(-1)
print(z)

输出结果:

deque([5, 6, 1, 2, 3, 4])
deque([6, 1, 2, 3, 4, 5])

5、clear()和 extend(iterable)方法

从上面我们可以知道deque里边的形式是列表形式,所以我们尝试用一下extend()。

from collections import deque
d = deque([1,2,3,4,5,6])
d.extend([7,8,9])
print(d)
d.clear()
print(d)

输出结果:

deque([1, 2, 3, 4, 5, 6, 7, 8, 9])
deque([])

6、insert() 和 count()方法

插入指定位置元素,例如insert(m,n),将n插入m位置。**count(i)**对在队列中的元素 i 计数

d = deque([1,2,3,4,5,6])
d.insert(1,0)
print(d)
print(d.count(1))

输出结果:

deque([1, 0, 2, 3, 4, 5, 6])
1

除了以上操作,deque 还可以使用迭代、封存、len(d)、copy.deepcopy(d)、成员检测运算符 in 以及下标引用例如通过 d[0] 访问首个元素等。 索引访问在两端的复杂度均为 O(1) 但在中间则会低至 O(n)。 如需快速随机访问,建议使用列表。

四、namedtuple()工厂函数

1、使用目的和方法

namedtuple()就是用来命名元组内部数据,让我们知道一个元组所要表达的意义,使用该函数可以构造一个带字段名的元组,并且具名元组和普通元组所占内存一样多,因为字段名都存放在类里面。
collections.namedtuple(typename, field_names, rename=False, defaults=None, module=None)
typename:元组名称
field_names:元组中元素名称,可以是一个列表,也可以是一个纯字符串用空 格或逗号隔开。
rename:默认为False,如果为True,元素名称中若有无效字段会转换成对应的位置名。例如:[‘x’,‘y’,‘for’]会转换成[‘x’,‘y’,’_2’]。
defaults:默认为None,也可以是一个可迭代对象,当filed_names元素名称多于元组元素,但又想要保留,就依次应用defaults中最右边的参数。
注:元素名称必须是有效python标识符,有效标识符由字母,数字,下划线组成,但首字母不能是数字或下划线,另外不能是关键词 keyword 比如 class, for, return, global, pass, 或 raise 。

from collections import namedtuple
a = namedtuple('a',['x','y','z','for'],rename=True,defaults=[3,4]) 
b = a(1,2)
print(b)
print(b.x)

输出结果:

a(x=1, y=2, z=3, _3=4)
1

2、类方法 somenamedtuple._make(iterable)

接受一个可迭代对象,创建类的实例

from collections import namedtuple
t = [2,3]
Point = namedtuple('Point','x,y')
print(Point._make(t))

输出结果:

Point(x=2, y=3)

3、类属性 somenamedtuple._fields

以元组的形式获取所有字段名

from collections import namedtuple
Point = namedtuple('Point','x,y')  
print(Point._fields)

输出结果:

('x', 'y')

4、somenamedtuple._replace()方法

返回一个新元组实例,并将原指定域替换为新的值

from collections import namedtuple
Point = namedtuple('Point','x,y')  
p = Point(10,15)
q = p._replace(x=25)  #返回新元组实例q(当然直接修改返回给p也可以)。
print(q)

输出结果:

Point(x=25, y=15)

5、somenamedtuple._asdict()方法

返回一个字典,字段名和值对应字典键值对

from collections import namedtuple
Point = namedtuple('Point','x,y') 
p = Point(10,15)
print(p._asdict())

输出结果:

{'x': 10, 'y': 15}

6、getattr()函数 和 ** 两星操作符的使用

getattr()用来获取指定名字对应的值,**操作符用来转换一个字典到命名元组

Point1 = namedtuple('Point1','name,age')
d = {'name':'mike','age':19}    
d1 = Point1('john',20) 
print(Point1(**d))        #转换一个字典到命名元组
print(getattr(d1,'name'))

输出结果:

Point1(name='mike', age=19)
john

这里插入一点之前使用过的 * 一星操作符使用
直接将列表里的元素转换为参数x,当然还有其他方面使用,这里不做介绍

a1 = ['a','s','d'] #直接将列表里的元素转换为参数x,等于print('a','s','b')
print(*a1)

输出结果:

a s d

五、OrderedDict对象

1、使用目的和方法

python中字典是按hash存储,所以我们认为它是无序的。但OrderedDict实现了对字典对象中元素的排序。返回一个dict子类的实例。所谓的排序,就是按字典插入顺序进行输出。

from collections import OrderedDict
d = OrderedDict()
d['name1'] = 'mike'
d['age1'] = 18
d['name2'] = 'john'
d['age2'] = 20
for k,v in d.items():
    print(k,v)

输出结果:

name1 mike
age1 18
money 422
name2 john
age2 20

2、popitem(last=True)和move_to_end(key, last=True)

popitem(last=True)有序字典的 popitem() 方法移除并返回一个 (key, value) 键值对。last为真,按后进先出返回键值对,last为假,则按先进先出返回键值对。就是分别移除最后一个或第一个键值对。
move_to_end()就是将字典中现有的key移动到指定的一端。last为真,将元素移至末尾,last为假,则移至开头。默认为真。

from collections import OrderedDict
d = OrderedDict()
d['name1'] = 'mike'
d['age1'] = 18
d['name2'] = 'john'
d['age2'] = 20
print(d)
d.popitem(last=True)
print(d)
d.move_to_end('name1',last=True)
print(d)
d.move_to_end('name1',last=False)
print(d)

输出结果:

OrderedDict([('name1', 'mike'), ('age1', 18), ('name2', 'john'), ('age2', 20)])
OrderedDict([('name1', 'mike'), ('age1', 18), ('name2', 'john')])
OrderedDict([('age1', 18), ('name2', 'john'), ('name1', 'mike')])
OrderedDict([('name1', 'mike'), ('age1', 18), ('name2', 'john')])

*以上就是我总结学习的一些collections容器数据类型内容,当然还有很多相关知识,具体学习大家可以参考:
*https://docs.python.org/zh-cn/3/library/collections.html#module-collections

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YYHhao.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值