深入Python中的 Collections 模块

时间:2022-10-16 19:47:29

深入Python中的 Collections 模块

collections模块是一个不用不知道,一用就上瘾的模块。这里主要介绍OrderedDict类、defaultdict类、Counter类、namedtuple类和deque类。

collections

collections的常用类型有:

  • 计数器(Counter)
  • 双向队列(deque)
  • 默认字典(defaultdict)
  • 有序字典(OrderedDict)
  • 可命名元组(namedtuple)

Counter

计数器(counter)以字典的形式返回序列中各个字符出现的次数,值为key,次数为value

Counter是对字典类型的补充,用于追踪值得出现次数 。

  1. import collections 
  2.  
  3. counter = collections.Counter("My name is Runsen"
  4. print(counter) 

输出如下

  1. Counter({' ': 3, 'n': 3, 'e': 2, 's': 2, 'M': 1, 'y': 1, 'a': 1, 'm': 1, 'i': 1, 'R': 1, 'u': 1}) 

取得元素重复次数的值

  1. print(counter[' ']) 

elements()取得计数器中的所有元素。

注:此处非所有元素集合,而是包含所有元素集合的迭代器.

  1. counter = collections.Counter('abcabcabcdabcdef')  
  2. print(counter) 
  3. # 输出如下 
  4. Counter({'a': 4, 'b': 4, 'c': 4, 'd': 2, 'e': 1, 'f': 1}) 
  5.  
  6. print(counter.elements()) 
  7. # 输出如下 
  8. <itertools.chain object at 0x0000025B1477BF98> 
  9.  
  10. print(list(counter.elements())) 
  11. # 输出如下 
  12. ['a''a''a''a''b''b''b''b''c''c''c''c''d''d''e''f'

将Counter按照value从大到小排列,获取前N个元素,需要使用函数most_common

  1. # most_common(N)数量从大到小排列,获取前N个元素  
  2. print(counter.most_common(3)) 
  3. # 输出如下 
  4. [('a', 4), ('b', 4), ('c', 4)] 

sorted将Counter中的key进行排序,返回的是所有key的列表

  1. # sorted()列出所有不同的元素并排序  
  2. print(sorted(counter)) 
  3.  
  4. # 输出如下 
  5. ['a''b''c''d''e''f'

将Counter转换成字符串,字符串的join方法可以解决。注意不是原来的模样。

  1. # 转换成字符串  
  2. print(''.join(counter.elements())) 
  3. # aaaabbbbccccddef 
  4. print(''.join(list(counter.elements()))) 

update()更新计数器,其实在原本的counter更新计数器,如果原来没有,则新建key,如果有value则加一

  1. update()更新计数器, 
  2. d = collections.Counter('a')  
  3. counter.update(d)  
  4. print(counter)  
  5. # 输出如下 
  6. Counter({'a': 5, 'b': 4, 'c': 4, 'd': 2, 'e': 1, 'f': 1}) 

update()更新计数器,那么subtract()相减计数器的values,即原来的计数器中的每一个元素的数量减去后添加的元素的数量

  1. counter.subtract('abdabcabcg')  
  2. print(counter) 
  3.  
  4. # 输出如下 
  5. Counter({'a': 2, 'c': 2, 'b': 1, 'd': 1, 'e': 1, 'f': 1, 'g': -1}) 

deque

deque支持从任意一端增加和删除元素。更为常用的两种结构,就是栈和队列。

deque的常见操作

  1. #定义一个空的双向队列 
  2. d = collections.deque() 
  3.  
  4. #从右端增加元素 
  5. d.extend("Runsen")  
  6. d.append("Maoli"
  7. d.append("Python"
  8. d.append("king"
  9.  
  10. #从左端增加元素 
  11. d.appendleft('left'
  12. print(d) 
  13. # 输出如下 (注意:extend和append的区别) 
  14. deque(['left''R''u''n''s''e''n''Maoli''Python''king']) 
  15.  
  16. # reverse()反转队列  
  17. print(d.reverse()) 
  18. d.reverse() 
  19. print(d) 
  20. # 输出如下 
  21. None 
  22. deque(['king''Python''Maoli''n''e''s''n''u''R''left']) 
  23.  
  24.  
  25. d.reverse() 
  26. d.extend(['qq','ww','ee'])  
  27. print(d)  
  28. # deque(['left''R''u''n''s''e''n''Maoli''Python''king''qq''ww''ee']) 
  29.  
  30.  
  31. count()计数  
  32. print(d.count('R')) 
  33. # 输出如下 
  34.  
  35. # clear()清空队列  
  36. d.clear()  
  37. print(d)  
  38. # 输出如下 
  39. deque([]) 
  40.  
  41. index()取得元素下标  
  42. print(d.index('Maoli')) 
  43. # 输出如下 
  44.  
  45. insert()指定位置插入元素  
  46. d.insert(1,'Runsen')  
  47. print(d)  
  48. # deque(['left''Runsen',R', 'u', 'n', 's', 'e', 'n', 'Maoli', 'Python', 'king', 'qq', 'ww', 'ee']) 

OrderedDict

使用dict时要保持Key的顺序,可以用OrderedDict。

  1. from collections import OrderedDict  
  2. dic = OrderedDict()  
  3. dic['k1'] = 'v1'  
  4. dic['k2'] = 'v2'  
  5. dic['k3'] = 'v3'  
  6. print(dic)  
  7. # 输出如下 
  8. OrderedDict([('k1''v1'), ('k2''v2'), ('k3''v3')]) 
  9.  
  10. # 字典所有的键  
  11. print(dic.keys()) 
  12. # 输出如下 
  13.  
  14. odict_keys(['k1''k2''k3']) 
  15.      
  16. # 字典所有值  
  17. print(dic.values()) 
  18. # 输出如下 
  19. odict_values(['v1''v2''v3']) 
  20.      
  21. # items() 方法以列表返回可遍历的(键, 值) 元组数组  
  22. print(dic.items()) 
  23.  
  24. # 输出如下 
  25. odict_items([('k1''v1'), ('k2''v2'), ('k3''v3')]) 
  26.      
  27.  
  28. #pop()方法,删除指定的键值  
  29. dic.pop('k1')   
  30. print(dic)  
  31. # 输出如下 
  32. OrderedDict([('k2''v2'), ('k3''v3')]) 
  33.  
  34.  
  35. #popitem()方法,默认删除字典最后一个元素  
  36. dic.popitem()  
  37. print(dic)  
  38. # 输出如下 
  39. OrderedDict([('k2''v2')]) 
  40.  
  41. update()更新字典  
  42. dic.update({'k1':'v1111','k10':'v10'})  
  43. print(dic)  
  44. # 输出如下 
  45. OrderedDict([('k2''v2'), ('k1''v1111'), ('k10''v10')]) 

OrderedDict和字典操作完全相同,区别在于OrderedDict的Key会按照插入的顺序排列,不是Key本身排序

  1. >>> from collections import OrderedDict 
  2. >>> d = dict([('a', 1), ('b', 2), ('c', 3)]) 
  3. >>> d # dict的Key是无序的 
  4. {'a': 1, 'c': 3, 'b': 2} 
  5. >>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)]) 
  6. >>> od # OrderedDict的Key是有序的 
  7. 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,如下举例:

  1. from collections import defaultdict 
  2.  
  3. dict1 = defaultdict(int
  4. dict2 = defaultdict(set
  5. dict3 = defaultdict(str) 
  6. dict4 = defaultdict(list) 
  7. dict1[2] ='two' 
  8.  
  9. print(dict1[1]) 
  10. print(dict2[1]) 
  11. print(dict3[1]) 
  12. print(dict4[1]) 
  13.  
  14. # 输出如下 
  15. set() 
  16.  
  17. [] 

defaultdict类接受类型名称作为初始化函数的参数,这样使得默认值的取值更加灵活。

  1. s = 'mynameisrunsen' 
  2. d = collections.defaultdict(int
  3. for k in s: 
  4.     d[k] += 1 
  5. print(d) 
  6.  
  7. # 输出如下 
  8. 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默认字典对列表进行划分。

  1. all_list = [11,22,33,44,55,66,77,88,99] 
  2. dic = collections.defaultdict(list) 
  3. for i in all_list: 
  4.     if i > 55: 
  5.         dic['k1'].append(i) 
  6.     else
  7.         dic['k2'].append(i) 
  8. print(dic) 
  9. # 输出如下 
  10. defaultdict(<class 'list'>, {'k2': [11, 22, 33, 44, 55], 'k1': [66, 77, 88, 99]}) 

也可以使用字典,具体代码如下。

  1. all_list = [11,22,33,44,55,66,77,88,99] 
  2. dic = {} 
  3. for i in all_list: 
  4.     if i > 55: 
  5.         if "k1" in dic.keys(): 
  6.             dic['k1'].append(i) 
  7.         else
  8.             dic['k1'] = [i,] 
  9.     else
  10.         if "k2" in dic.keys(): 
  11.             dic['k2'].append(i) 
  12.         else
  13.             dic['k2'] = [i,] 
  14. print(dic) 
  15. # 输出如下 
  16. {'k2': [11, 22, 33, 44, 55], 'k1': [66, 77, 88, 99]} 

namedtuple

namedtuple是用来创建一个自定义的tuple对象,并且规定了tuple元素的个数,并可以用属性而不是索引来引用tuple的某个元素。

使用命名元组的步骤:

  1. # 将元组封装为一个类,可以通过字段名(属性名)来访问元组中的值 
  2. # 支持元组的所有操作 
  3. from collections import namedtuple 
  4. # 1、定义一个类 
  5. Runsen = namedtuple('Runsen', ['name','sex','age']) 
  6. # 2、创建对象 
  7. runsen = Runsen("Runsen""帅男", 21) 
  8. # 3、获取命名元组的值 
  9. print(runsen[1])    # 支持元组的索引取值   
  10. print(runsen[-2:])  # 支持切片 
  11. print(runsen.name)  # 支持通过字段名来取值  
  12. # _fields,获取命名元组的所有属性名 
  13. print(runsen._fields) 
  14. # _asdict方法,将元组转化为字典 
  15. print(runsen._asdict()) 
  16.  
  17. # 输出如下 
  18.  
  19. 帅男 
  20. ('帅男', 21) 
  21. Runsen 
  22. ('name''sex''age'
  23. OrderedDict([('name''Runsen'), ('sex''帅男'), ('age', 21)]) 

本文已收录 GitHub,传送门~[1] ,里面更有大厂面试完整考点,欢迎 Star。

Reference

[1]传送门~:

https://github.com/MaoliRUNsen/runsenlearnpy100