collections模块的使用

collections模块基于Python中内置的dict、list、set和tuple数据类型实现了一些专门的容器,来扩展这些基础类型变量的功能。

namedtuple

原始的tuple只能通过index的方式访问所包含的元素,namedtuple就相当于为tuple和tuple中的元素取了新的名字,操作的时候可以用这些名字直接去访问(这种操作好像跟C里面的struct差不多耶)。这种设置可以让我们定义tuple变量的目的一目了然,所以用好它可以让我们的代码更易于维护。下面来看看具体怎么用吧!

# 现在我们想要定义一个类型专门用于保存坐标
# 构造一个类专门去保存好像有点麻烦
# 这时namedtuple就派上用场啦

# 执行结果在下方
from collections import namedtuple
Posi = namedtuple('Positions', ('x', 'y'))
p = Posi(1, 2)	# 创建对象时记住要用Posi,Positions只是一个标识的名称
print(p)
# Positions(x=1, y=2)
print(p.x, p.y)	# 记住tuple是不可修改的,所以不能给p.x重新赋值
# 1 2

没错,实例化的对象打印出来的就是我们前面给它定义的名字,元素名称也可以用我们给的名字来获得。比起老式的tuple,namedtuple简直是太贴心,一眼就能看出来作用了。

deque

deque是一个对list进行功能扩展的方法,说白了就是把list改成了一个双端队列,可用于栈和队列。虽然list对象也支持类似的操作,但是由于线性存储插入和删除元素的时间复杂度是O(n),当数据量很大时效率很低。deque里面有许多操作方法:

from collections import deque
que1 = deque([1,2,3,4,5])
que1.append(5)		# 向右添加元素
print(que1)
# deque([1, 2, 3, 4, 5, 5])
que1.appendleft(0)		# 向左添加元素
print(que1)
# deque([0, 1, 2, 3, 4, 5, 5])
que2 = que1.copy()		# 浅拷贝一个deque对象
print(que1,que2)
# deque([0, 1, 2, 3, 4, 5, 5]) deque([0, 1, 2, 3, 4, 5, 5])
que1.clear()	# 清空deque中元素
print(que1)
#deque([])
print(que2.count(5))	# 统计某一个元素的个数
# 2
que2.extend([6,7])		# 从右合并
que2.extendleft([-1,-2])	# 往左扩展时是倒序合并
print(que2)
# deque([-2, -1, 0, 1, 2, 3, 4, 5, 5, 6, 7])
que2.insert(4,1)	# 向指定位置插入元素,前一个参数为位置,后一个为值
print(que2)
# deque([-2, -1, 0, 1, 1, 2, 3, 4, 5, 5, 6, 7])
que2.pop()	# 右弹出值
que2.popleft()	# 坐弹出值
print(que2)
# deque([-1, 0, 1, 1, 2, 3, 4, 5, 5, 6])
que2.remove(1)	# 删除第一个找到的值
print(que2)
# deque([-1, 0, 1, 2, 3, 4, 5, 5, 6])
que2.reverse()
print(que2)		# 将deque对象中的元素倒排
# deque([6, 5, 5, 4, 3, 2, 1, 0, -1])
que2.rotate(2)		# 将右边的N个元素弹出并插入到左边
print(que2)
# deque([0, -1, 6, 5, 5, 4, 3, 2, 1])

ChainMap

ChainMap提供了一种可以将多个映射作为一个单元处理的策略。它往往比创建一个新字典然后用update()将原字典合并来的快得多。需要注意的是ChainMap是通过引用的方式来合并所有映射对象中的元素,所以当原映射对象中的元素改变时,合并后对象中的内容也会改变。

from collections import ChainMap

attr1 = {'name':'Tom','Age':18}
attr2 = {'gender':'man','addr':'Beijing'}
people = ChainMap(attr1,attr2)	# 合并两个字典
print(people)
# ChainMap({'name': 'Tom', 'Age': 18}, {'addr': 'Beijing', 'gender': 'man'})
print(people['name'])
# Tom
attr1['name'] = 'Micheal'
print(attr1['name'], people['name'])	# 修改原字典中的值,合并后列表中的值也会改变
# Micheal Micheal
people = people.new_child({'country':'America'})	# new_child为ChainMap实例合并新字典
print(people)
# ChainMap({'country': 'America'}, {'name': 'Micheal', 'Age': 18}, {'addr': 'Beijing', 'gender': 'man'})
print(people.parents)		# parents属性指定的是父级内容,即实例变化前的内容
# ChainMap({'name': 'Micheal', 'Age': 18}, {'addr': 'Beijing', 'gender': 'man'})
print(people.parents.parents)		# 父级的父级内容
#ChainMap({'addr': 'Beijing', 'gender': 'man'})
print(people.maps)		# maps属性返回的是将合并后的ChainMap实例拆分并保存为list的结果,是最新的结果
# [{'country': 'America'}, {'name': 'Micheal', 'Age': 18}, {'addr': 'Beijing', 'gender': 'man'}]
print(people)
# ChainMap({'country': 'America'}, {'name': 'Micheal', 'Age': 18}, {'addr': 'Beijing', 'gender': 'man'})

counter

counter提供的是一个方便又快速的计数器,统计出来的计数是用字典保存的,字段保存为key,出现次数保存为value。Counter可以读取任何字段的计数,不存在的字段默认计数为0,value值也可以为负。使用方法如下:

from collections import Counter

c1 = Counter('hello world')
print(c1)
# Counter({'l': 3, 'o': 2, ' ': 1, 'e': 1, 'w': 1, 'h': 1, 'd': 1, 'r': 1})
c2 = Counter({'man':4, 'woman':2})
print(c2)
# Counter({'man': 4, 'woman': 2})
c3 = Counter(child=3, young=1,old=2)
print(c3.most_common(2))	# most_common方法会返回计数排名前N的元素
# [('child', 3), ('old', 2)]
print(list(c3.elements()))	# elements方法返回一个迭代器,里面包含所有的key,数量与计数对应
# ['young', 'old', 'old', 'child', 'child', 'child']
c4 = Counter(child=2,young=1,old=1)
c3.subtract(c4)		# subtract方法用于从一个counter中减掉另一个counter,key相同时对计数做减法
print(c3)
# Counter({'old': 1, 'child': 1, 'young': 0})
c5 = Counter(middle=3)
c4.subtract(c5)
print(c4)
# Counter({'child': 2, 'young': 1, 'old': 1, 'middle': -3})
del c3['child']	# del用于从字典中删除某一个元素,这类操作同样适用于Counter实例
print(c3['child'])
# 0

fruits1 = Counter({'apple':3,'orange':5,'banana':7})
fruits2 = Counter({'orange':2,'apple':1,'pear':4})
print(fruits1 - fruits2)	# Counter实例还可进行加减运算和按位与或
# Counter({'banana': 7, 'orange': 3, 'apple': 2})
print(fruits1 + fruits2)
# Counter({'banana': 7, 'orange': 7, 'pear': 4, 'apple': 4})
print(fruits1 & fruits2)
# Counter({'orange': 2, 'apple': 1})
print(fruits1 | fruits2)
# Counter({'banana': 7, 'orange': 5, 'pear': 4, 'apple': 3})

还需要注意的是,一些对字典的常规操作同样对Counter也有效。但是fromkeys()在这里不能作用于Counter实例,update()在这里是新增Counter而不是代替旧的Counter,这两种方法是例外。

OrderDict

常规的dict是随机存储的,这就导致了我们对dict进行迭代的时候无法确元素的顺序。OrderDict能够有效的解决这个问题,但是返回的是插入时的顺序,而不是根据key来排序(如果一开始就定义了元素,输出时是随机顺序输出的)。

from collections import OrderedDict
d = OrderedDict(a=1,b=2,c=3)
print(d)
# OrderedDict([('c', 3), ('a', 1), ('b', 2)])
print(d)
# OrderedDict([('c', 3), ('a', 1), ('b', 2)])
d['d'] = 4
print(d)
# OrderedDict([('c', 3), ('a', 1), ('b', 2), ('d', 4)])
print(d)	# 元素按照固定顺序排列
# OrderedDict([('c', 3), ('a', 1), ('b', 2), ('d', 4)])
d = OrderedDict.fromkeys('abbcde')
print(d)
# rderedDict([('a', None), ('b', None), ('c', None), ('d', None), ('e', None)])
d.move_to_end('b')		# 将指定元素移动到末尾
print(d.keys())
# odict_keys(['a', 'c', 'd', 'e', 'b'])
d.move_to_end('d',last=False)		# 将指定元素移动到头部
print(d.keys())
# odict_keys(['d', 'a', 'c', 'e', 'b'])
d.popitem()		# 移除末尾元素
print(d.keys())
# odict_keys(['d', 'a', 'c', 'e'])
d.popitem(last=False)		# 移除首部元素
print(d.keys())
# dict_keys(['a', 'c', 'e'])

defaultdict

一般的dict,如果试图访不存在的Key则会抛出KeyError错误。如果希望Key不存在的时候返回一个默认的value值,那么defaultdict就派上用场了。(注意默认值是通过调用函数来带回值)

from collections import defaultdict
dd = defaultdict(lambda : 0)
dd['a'] = 1
print(dd['a'])
# 1
print(dd['b'])
# 0

UserDict

用户自定义字典类,可以继承该类并重写规则。初始化时可以用来拷贝一个字典的数据,而不是简单的引用。

from collections import UserDict
dict = {'a':1,'b':2}
ud = UserDict(dict)
print(dict, ud)
# {'b': 2, 'a': 1} {'b': 2, 'a': 1}
ud['c'] = 3
print(dict, ud)
# {'b': 2, 'a': 1} {'c': 3, 'b': 2, 'a': 1}

UserList

用户自定义列表类,可以继承该类并重写规则。构建一个用户自定义列表,初始化时可以拷贝另外一个列表中的内容。

from collections import UserList
li = [1,2,3,4]
l = li
ul = UserList(li)
del li[0]
print(l, li, ul)
# [2, 3, 4] [2, 3, 4] [1, 2, 3, 4]

UserString

用户自定义字符串类,可以继承该类并重写规则。初始化时可以拷贝一个字符串。

from collections import UserString

s = 'hello world!'
us = UserString(s)
print(s, us)
# hello world! hello world!

转载请注明出处,如有不正之处还望矫正,谢谢

猜你喜欢

转载自my.oschina.net/u/3723649/blog/1570794