python标准库系列教程(四)——collections库详细教程
python进阶教程
机器学习
深度学习
长按二维码关注
进入正文
声明:python标准库的系列文章已经更新了三大篇文章,前面更新了functools, itertools, operator这三大支持函数式编程的三大模块,但是python标准库中还有很多非常重要、非常高效的库,本文介绍的collections模块便是其中之一,它包含了一些常用的数据结构,能够让我们非常快捷方便的使用相关的数据结构,系列文章分篇连载,此为第四篇,鉴于内容较多,介绍的都是collections库里面的一些常见数据结构,详细内容可以参阅相关文档。有兴趣的小伙伴后面记得关注学习哦!
Python之Collections系列以及用法
目录
1 Counter
2 deque
3 defaultdict
4 Orderdict
5 nametuple
6 ChainMap
7 其它简介
01
Counter
Counter 作为字典(dict)的一个子类用来进行hashtable计数,将元素进行数量统计、计数后返回一个字典,键值为元素:值为元素个数
s = 'abcbcaccbbad'
l = ['a','b','c','c','a','b','b']
d = {'2': 3, '3': 2, '17': 2}
# Counter 获取各元素的个数,返回字典
print(Counter(s)) # Counter({'c': 4, 'b': 4, 'a': 3})
print(Counter(l)) # Counter({'b': 3, 'a': 2, 'c': 2})
print(Counter(d)) # Counter({3: 3, 2: 2, 17: 1})
most_common
# most_common(int) 按照元素出现的次数进行从高到低的排序,返回前int个元素的字典
m1 = Counter(s)
print(m1) # Counter({'c': 4, 'b': 4, 'a': 3, 'd': 1})
print(m1.most_common(3)) # [('c', 4), ('b', 4), ('a', 3)]
elements
# elements 返回经过计数器Counter后的元素,返回的是一个迭代器
e1 = Counter(s)
print(''.join(sorted(e1.elements()))) # aaabbbbcccc
e2 = Counter(d)
print(sorted(e2.elements())) # ['17', '17', '2', '2', '2', '3', '3'] 字典返回value个key
update
# update 和set集合的update一样,对集合进行并集更新
u1 = Counter(s)
u1.update('123a')
print(u1) # Counter({'a': 4, 'c': 4, 'b': 4, '1': 1, '3': 1, '2': 1})
substract
# substract 和update类似,只是update是做加法,substract做减法,从另一个集合中减去本集合的元素,
sub1 = 'which'
sub2 = 'whatw'
subset = Counter(sub1)
print(subset) # Counter({'h': 2, 'i': 1, 'c': 1, 'w': 1})
subset.subtract(Counter(sub2))
print(subset) # Counter({'c': 1, 'i': 1, 'h': 1, 'a': -1, 't': -1, 'w': -1}) sub1中的h变为2,sub2中h为1,减完以后为1
iteritems
与字典dict的items类似,返回由Counter生成的字典的所有item,只是在Counter中此方法返回的是一个迭代器,而不是列表
iterkeys
与字典dict的keys方法类似,返回由Counter生成的字典的所有key,只是在Counter中此方法返回的是一个迭代器,而不是列表
itervalues
与字典dict的values方法类似,返回由Counter生成的字典的所有value,只是在Counter中此方法返回的是一个迭代器,而不是列表02
deque
deque 包含在文件_collections.py中,属于高性能的数据结构(High performance data structures)之一.可以从两端添加和删除元素,常用的结构是它的简化版。
deque常用方法:
deque
str1 = 'abc123cd'
dq = deque(str1)
print(dq) # deque(['a', 'b', 'c', '1', '2', '3', 'c', 'd'])
appendleft
队列左边添加元素
dq = deque('abc123')
dq.append('right')
dq.appendleft('left')
print(dq) # deque(['left', 'a', 'b', 'c', '1', '2', '3', 'right'])
clear
clear 清空队列中的所有元素count
count(value) 返回队列中包含value的个数,结果类型为 integerextend
extend 队列右边扩展,可以是列表、元组或字典,如果是字典则将字典的key加入到deque
extendleft
extendleft 同extend, 在左边扩展
dq = deque('abc123')
dq.extend({1:10,2:20})
dq.extendleft('L')
print(dq) # deque(['L', 'a', 'b', 'c', '1', '2', '3', 1, 2])
pop
pop 移除并且返回队列右边的元素
popleft
popleft 移除并且返回队列左边的元素
remove
remove(value) 移除队列第一个出现的元素(从左往右开始的第一次出现的元素value)
reverse
reverse 队列的所有元素进行反转
rotate
rotate(n) 对队列的数进行移动,若n<0,则往左移动即将左边的第一个移动到最后,移动n次,n>0 往右移动
dq = deque([1,2,3,4,5])
dq.rotate(-1) # 左移,1往左移动一位到5后面
print(dq)
03
defaultdict
dic = collections.defaultdict(dict)
dic['k1'].update({'k2':'aaa'})
print(dic)
我们看上面的例子,字典dic在定义的时候就定义好了值为字典类型,虽然现在字典中还没有键值 k1,但仍然可以执行字典的update方法. 这种操作方式在传统的字典类型中是无法实现的,必须赋值以后才能进行值得更新操作,否则会报错。我看看一下传统的字典类型
b = dict()
b['k1'].append('2')
# TypeError: 'type' object is not iterable
04
OrderDict
OrderDict 叫做有序字典,也是字典类型(dict)的一个子类,是对字典的一个补充。 前面我们说过,字典类型是一个无序的集合,如果要想将一个传统的字典类型进行排序一般会怎么做了,我们可能会将字典的键值取出来做排序后在根据键值来进行有序的输出,我们看下面的一个例子:
# 定义传统字典
dic1 = dict()
# 按顺序添加字典内容
dic1['a'] = '123'
dic1['b'] = 'jjj'
dic1['c'] = '394'
dic1['d'] = '999'
print(dic1) # 结果: {'a': '123', 'c': '394', 'b': 'jjj', 'd': '999'}
# 排序
dic1_key_list = []
for k in dic1.keys():
dic1_key_list.append(k)
dic1_key_list.sort()
for key in dic1_key_list:
print('dic1字典排序结果 %s:%s' %(key,dic1[key]))
以上为定义传统字典类型时的一个简单排序过程。 如果我们定义一个有序字典时,将不用再如此麻烦, 字典顺序将按照录入顺序进行排序且不会改变。
# 定义有序字典
dic2 = OrderedDict()
dic2['a'] = '123'
dic2['b'] = 'jjj'
dic2['c'] = 'abc'
dic2['d'] = '999'
for k, v in dic2.iteritems():
print('有序字典:%s:%s' %(k,v))
05
nametuple
标准的tuple类型使用数字索引来访问元素,
bob = ('Bob', 30, 'male')
print('Representation:', bob)
jane = ('Jane', 29, 'female')
print('\nField by index:', jane[0])
print('\nFields by index:')
for p in [bob, jane]:
print('%s is a %d year old %s' % p)
这种对于标准的元组访问,我们需要知道元素对应下标索引值,但当元组的元素很多时,我们可能无法知道每个元素的具体索引值,这个时候就是可命名元组登场的时候了。nametuple 的创建是由自己的类工厂nametuple()进行创建,而不是由标准的元组来进行实例化,通过nametuple()创建类的参数包括类名称和一个包含元素名称的字符串
from collections import namedtuple
#创建一个nametuplede 类,类名称为Person,并赋给变量P
P = namedtuple('Person', 'name,age,gender')
print('Type of Person:', type(P)) # Type of Person: <class 'type'>
#通过Person类实例化一个对象bob
bob = P(name='Bob', age=30, gender='male')
print('\nRepresentation:', bob) # Representation: Person(name='Bob', age=30, gender='male')
#通过Person类实例化一个对象jane
jane = P(name='Jane', age=29, gender='female')
print('\nField by name:', jane.name) # Field by name: Jane
print('\nFields by index:')
for p in [bob, jane]:
print('%s is a %d year old %s' % p)
# Fields by index:
# Bob is a 30 year old male
# Jane is a 29 year old female
通过上面的实例可以看出,我们通过nametuple()创建了一个Person的类,并复制给P变量,Person的类成员包括name,age,gender,并且顺序已经定了,在实例化zhangsan这个对象的时候,对张三的属性进行了定义。这样我们在访问zhangsan这个元组的时候就可以通过张三的属性来复制(zhangsan.name、zhangsan.age等)。这样就算这个元组有1000个元素我们都能通过元素的名称来访问而不用考虑元素的下标索引值。06
ChainMap
ChainMap用来将多个dict(字典)组成一个list(只是比喻),可以理解成合并多个字典,但和update不同,而且效率更高。
>>> from collections import ChainMap
>>> a = {'a': 'A', 'c': 'C'}
>>> b = {'b': 'B', 'c': 'D'}
>>> m = ChainMap(a, b)
# 构造一个ChainMap对象
>>> m
ChainMap({'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})
>>> m['a']
'A'
>>> m['b']
'B'
# 将m变成一个list
>>> m.maps
[{'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'}]
# 更新a中的值也会对ChainMap对象造成影响
>>> a['c'] = 'E'
>>> m['c']
'E'
# 从m复制一个ChainMap对象,更新这个复制的对象并不会对m造成影响
>>> m2 = m.new_child()
>>> m2['c'] = 'f'
>>> m['c']
'E'
>>> a['c']
'E'
>>> m2.parents
ChainMap({'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})
07
其它简介
当然这个库里面所定义的数据结构很多,远远不止上面这几种,常见的一些如下:
['AsyncGenerator',
'AsyncIterable',
'AsyncIterator',
'Awaitable',
'ByteString',
'Callable',
'ChainMap',
'Collection',
'Container',
'Coroutine',
'Counter',
'Generator',
'Hashable',
'ItemsView',
'Iterable',
'Iterator',
'KeysView',
'Mapping',
'MappingView',
'MutableMapping',
'MutableSequence',
'MutableSet',
'OrderedDict',
'Reversible',
'Sequence',
'Set',
'Sized',
'UserDict',
'UserList',
'UserString',
'ValuesView',
'_Link',
'_OrderedDictItemsView',
'_OrderedDictKeysView',
'_OrderedDictValuesView',
'__all__',
'__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__path__',
'__spec__',
'_chain',
'_class_template',
'_collections_abc',
'_count_elements',
'_eq',
'_field_template',
'_heapq',
'_iskeyword',
'_itemgetter',
'_proxy',
'_recursive_repr',
'_repeat',
'_repr_template',
'_starmap',
'_sys',
'abc',
'defaultdict',
'deque',
'namedtuple']
小结
从上面的例子可以看出,我们使用collections标准库所带的数据结构,比我们自己去定义实现是更加方便快捷的,在平时的编程中,我们也应该尽可能使用标准数据结构。
2019/01/02
Thuesday
小伙伴们,collections标准库一定要好好学哦,看完这篇文章,是不是有所收获呢?后面还有系列文章连载,请记得关注哦!如果你有需要,就添加我的公众号哦,里面分享有海量资源,包含各类数据、教程等,后面会有更多面经、资料、数据集等各类干货等着大家哦,重要的是全都是免费、无套路分享,有兴趣的小伙伴请持续关注!
2.python标准库系列教程(二)——functools (下篇)
3. numpy高级教程(一)——高级数组操作与广播broadcast
4. numpy高级教程(二)——通用函数ufunc与结构化数组structured array
5. python标准库系列教程(一)——itertools
6. python标准库系列教程(二)——functools (上篇)
7.python标准库系列教程(三)——operator库详细教程
8.Python高级编程——描述符Descriptor超详细讲解(补充篇之底层原理实现)
9.Python高级编程——描述符Descriptor超详细讲解(中篇之属性控制)
赶紧关注我们吧
您的点赞和分享是我们进步的动力!
↘↘↘