摘要:collections模块里面常用类介绍,包括nametuple、deque、defaultdict、Ordereddict、Counter
写在前面:为了更好的学习python,博主记录下自己的学习路程。本学习笔记基于廖雪峰的Python教程,如有侵权,请告知删除。欢迎与博主一起学习Pythonヽ( ̄▽ ̄)ノ
目录
collections是Python内建的一个集合模块,提供了许多有用的集合类,可以说是tuple、list、dict等集合的功能补充。
namedtuple,具名元组。由于tuple不能给元素命名,导致往往不知道该元素表达的意思,于是就有了namedtuple
。
namedtuple
是一个函数,它可以创建一个自定义tuple
类型,并规定tuple的元素个数,而且能够用属性而不是索引来引用指定元素,换而言之,就是可以给元素命名。
比如我们要用坐标来表示一个点,就可以通过namedtuple
定义一个Point
类型:
>>>from collections import namedtuple
>>>Point = namedtuple('Point', ['x', 'y']) # 通过namedtuple函数定义一个Point类,并设置两个属性x,y
>>>p = Point(1, 2) # 创建一个Point类的实例p,赋予属性x为1,属性y为2
>>>p.x
1
>>>p.y
2
比如我们要表示一个圆,可以这样定义一个Circle
类型:
Circle = namedtuple('Circle', ['x', 'y', 'r'])
需要注意的是Ponit
或Circle
的实例对象也是tuple
,它具有tuple的所有特性如不变性。而namedtuple
是一个函数。
>>>type(p)
<class '__main__.Point'>
>>>isinstance(p, tuple)
True
>>>type(namedtuple)
<class 'function'>
deque,双端队列。由于list是线性储存,在数据量大时虽然可以很快地根据索引来访问元素,但是插入或删除元素的效率很低。
deque
是实现可双端插入或删除元素的双端列表,提高了效率,适用于队列和栈。
>>>from collections import deque
>>>q = deque(['a', 'b', 'c'])
>>>q.append('x') # 右边添加元素
>>>q.appendleft('y') # 左边添加元素
>>>print(q)
deque(['y', 'a', 'b', 'c', 'x'])
>>>q.pop() # 删除右边的第一个元素
>>>q.popleft() # 删除左边的第一个元素
deque(['a', 'b', 'c'])
>>>print(q)
可见deque
实现从队列的头部或尾部添加或删除元素的功能。
在使用dict
时,如果调用的key
不存在,则会抛出keyerror
。如果希望key
不存在时返回其他值,可以用defaultdict。
>>>from collections import defaultdict
>>>dd = defaultdict(lambda: 'NO KEY')
>>>dd['key1'] = 'aaa'
>>>dd['key1']
aaa
>>>dd['key2']
NO KEY
通过defaultdict
创建的对象也是dict
:
>>>isinstance(dd, dict)
True
OrderedDict,有序字典。
在Python3.6版之前,dict
是无序的,也就是dict内部存放的顺序与key
放入的顺序无关:
d = dict()
d['a']='A'
d['b']='B'
d['c']='C'
for k,v in d.items():
print(k,v)
运行结果:
a A
c C
b B
OrderedDict
是有序的:
from collections import OrderedDict
od = OrderedDict()
od['a']='A'
od['b']='B'
od['c']='C'
for k,v in od.items():
print(k,v)
运行结果:
a A
b B
c C
当然,在Python3.6及之后的版本,dict也是有序的了。那么还要OrderedDict
有什么用呢?其实OrderedDict
还有其他功能。
我们都知道,通过popitem( )
可以删除dict的元素,但只能删除最后添加的元素。
在OrderedDict
中,popitem( )
可以设置last
参数,last
默认为True
,即以LIFO(后进先出)的原则来删除元素;把last
改为False
,则以FIFO(先进先出)的原则来删除元素。
下面是实现FIFO的一个例子(代码除注释转自廖雪峰官网):
from collections import OrderedDict
class LastUpdatedOrderedDict(OrderedDict):
def __init__(self, capacity):
# LastUpdatedOrderedDict沿用OrderedDict类的参数定义
super(LastUpdatedOrderedDict, self).__init__()
self._capacity = capacity # 设置容量参数
def __setitem__(self, key, value):
containsKey = 1 if key in self else 0 # 如果将传入的key已有,则containsKey为1,反之0
if len(self) - containsKey >= self._capacity: # 如果原本key数目大于等于容量,且不是传入重复的key
last = self.popitem(last=False) # 以先进先出的原则,移除最早添加的元素
print('remove:', last) # 打印:移除最早添加的元素
if containsKey:
del self[key] # 如果传入相同的key,则删除旧的key
print('set:', (key, value)) # 打印:设置key新的value
else:
print('add:', (key, value)) # 打印:添加新key与value
我们来试一下这个新定义的类:
>>>lod = LastUpdatedOrderedDict(3)
>>>lod['a']=1 # 尝试添加key'a'
add: ('a', 1) # 成功添加
>>>lod
LastUpdatedOrderedDict([('a', 1)])
>>>lod['b']=2 # 尝试添加key'b'
add: ('b', 2) # 成功添加
>>>lod
LastUpdatedOrderedDict([('a', 1), ('b', 2)])
>>>lod['c']=3 # 尝试添加key'c'
add: ('c', 3) # 成功添加
>>>lod
LastUpdatedOrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>>lod['d']=4 # 尝试添加key'd'
remove: ('a', 1) # 由于已达容量个数,移除最早添加的key'a'
add: ('d', 4) # 继续添加key'd'
>>>lod
LastUpdatedOrderedDict([('b', 2), ('c', 3), ('d', 4)])
>>>lod['b']=10 # 尝试添加key'b'
set: ('b', 10) # 由于key'b'已有,删除原有的'b',添加新的b
>>>lod
LastUpdatedOrderedDict([('d', 4), ('c', 5), ('b', 10)])
代码解析:我觉得必要再说明一下这行代码:
if len(self) - containsKey >= self._capacity:
len(self)
是查看原本dict的元素个数,不包括将要添加的元素。在我们的设定中,len(self)
只能小于等于self._capacity
,不会存在大于self._capacity
的情况。
当传入的key
与原有的key
不重复,即containsKey
为0时。在len(self) == self._capacity
,即原有的元素个数达到容量个数,会执行if
后的缩进语句;
当传入的key
与原有的key
重复,即containsKey
为1时。len(self) - containsKey
一定是小于self._capacity
的,这种情况是不会执行if
后的缩进语句的。
最后说明一下OrderedDict
创建的对象也是dict
类,如上例创建的lod
对象:
>>>isinstance(lod, dict)
True
Counter,计数器。顾名思义,Counter
是一个实现计数功能的类,使用如下:
>>>from collections import Counter
>>>c = Counter()
>>>for ch in 'hello world':
... c[ch] = c[ch] + 1
...
>>>c
Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
以上就是本节的全部内容,感谢你的阅读。
下一节内容:常用内置模块之 base64和struct
有任何问题与想法,欢迎评论与吐槽。
和博主一起学习Python吧( ̄▽ ̄)~*