Python中collections模块(高性能集合操作)的用法详解

序号 方法 功能 返回值类型 示例
1 namedtuple() 定义了一个返回值为tuple的类
  • (1)这个类能使用【下标】获取元素外
  • (2)这个类还能通过【属性】获取元素。
tuple
  • User = namedtuple("Student",["name", "age", "weight"])
  • user = User(“admin”, “20”, “60”)
  • print(user)
    >>>Student(name=‘admin’, age=‘20’, weight=‘60’)
2 ChainMap() 将多个字典集合到一个字典,并对外提供一个统一视图 dict
  • user1 = {“name”:“admin”, “age”:“20”}
  • user2 = {“name”:“root”, “weight”: 65}
  • users = ChainMap(user1, user2)
  • print(users.maps)
    >>>[{‘name’: ‘admin’, ‘age’: 20}, {‘name’: ‘root’, ‘weight’: 65}]
3 deque() 一种类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)操作。 list
  • q = deque([1,2,3])
  • q.append(‘4’) # 在list的右侧添加元素’4‘
  • q.appendleft(‘0’) # 在list的左侧添加元素’0‘
  • print(q)
    >>>deque([‘0’, 1, 2, 3, ‘4’])
4 Counter() 一个计数器,可以统计每个元素出现的次数 dict
  • animals = [“cat”, “dog”, “cat”, “bird”, “horse”, “tiger”, “horse”, “cat”]
  • animals_counter = Counter(animals)
  • print(animals_counter)
    >>>Counter({‘cat’: 3, ‘horse’: 2, ‘dog’: 1, ‘bird’: 1, ‘tiger’: 1})
5 OrderedDict() 是字典的子类,保证了元素的插入顺序 dict
  • user = OrderedDict()
  • user[“name”] = “admin”
  • user[“age”] = 23
  • user[“weight”] = 65
  • print(user)
    >>>OrderedDict([(‘name’, ‘admin’), (‘age’, 23), (‘weight’, 65)])
6 defaultdict() 内置 dict 类的子类,它实现了当 key 不存在时返回默认值的功能 dict
  • default_dict = defaultdict(int)
  • default_dict[‘x’] = 10
  • print(default_dict[‘x’])
    >>>10
  • print(default_dict[‘y’])
    >>>0

绪论

Python中内置了4种数据类型,包括:listtuplesetdict,这些数据类型都有其各自的特点,但是这些特点(比如dict无序)在一定程度上对数据类型的使用产生了约束,在某些使用场景下效率会比较低,比如:有时候我们可能需要维护一个有序的字典等情况。

在这种场景下我们可以使用Python内建的collections模块,它包括了很多有用的集合类,合理的使用可以提高我们代码的运行效率。

0.0 collections模块的信息检索

1、查看collections模块的定义路径:collections.__file__

典型范例:

import collections
# 查看属性:__file__:查看collections模块的定义路径
collections.__file__
>>>
'/Users/zhang/opt/miniconda3/envs/py37tf114/lib/python3.7/collections/__init__.py'

2、查看collections文档介绍信息:collections.__doc__

import collections
# 查看属性:__doc__:查看collections文档介绍信息
print(collections.__doc__)
>>>
This module implements specialized container datatypes providing
alternatives to Python's general purpose built-in containers, dict,
list, set, and tuple.

* namedtuple   factory function for creating tuple subclasses with named fields
* deque        list-like container with fast appends and pops on either end
* ChainMap     dict-like class for creating a single view of multiple mappings
* Counter      dict subclass for counting hashable objects
* OrderedDict  dict subclass that remembers the order entries were added
* defaultdict  dict subclass that calls a factory function to supply missing values
* UserDict     wrapper around dictionary objects for easier dict subclassing
* UserList     wrapper around list objects for easier list subclassing
* UserString   wrapper around string objects for easier string subclassing

3、查看collections的所有可用的类、方法和属性:dir(collections)

# 使用函数dir():查看collections的所有可用的类、方法和属性
print(dir(collections))
>>>
['ChainMap', 'Counter', 'OrderedDict', 'UserDict', 'UserList', 'UserString', '_Link', 
'_OrderedDictItemsView', '_OrderedDictKeysView', '_OrderedDictValuesView', '__all__',
 '__builtins__', '__cached__', '__doc__', '__file__', '__getattr__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '_chain', '_collections_abc', 
 '_count_elements', '_eq', '_heapq', '_iskeyword', '_itemgetter', '_nt_itemgetters', 
 '_proxy', '_recursive_repr', '_repeat', '_starmap', '_sys', 'abc', 'defaultdict', 
 'deque', 'namedtuple']

参考链接:python内置collections模块的使用

4、查看collections模块下的某个函数或方法有哪些属性。例如:dir(namedtuple)

# 使用函数dir():查看一下namedtuple有哪些属性
print(dir(namedtuple))
>>>
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

5、查看collections模块下的某个函数或方法的官方文档。例如:namedtuple.__doc__

扫描二维码关注公众号,回复: 14871896 查看本文章
print(namedtuple.__doc__)
>>>
Returns a new subclass of tuple with named fields.

    >>> Point = namedtuple('Point', ['x', 'y'])
    >>> Point.__doc__                   # docstring for the new class
    'Point(x, y)'
    >>> p = Point(11, y=22)             # instantiate with positional args or keywords
    >>> p[0] + p[1]                     # indexable like a plain tuple
    33
    >>> x, y = p                        # unpack like a regular tuple
    >>> x, y
    (11, 22)
    >>> p.x + p.y                       # fields also accessible by name
    33
    >>> d = p._asdict()                 # convert to a dictionary
    >>> d['x']
    11
    >>> Point(**d)                      # convert from a dictionary
    Point(x=11, y=22)
    >>> p._replace(x=100)               # _replace() is like str.replace() but targets named fields
    Point(x=100, y=22)

6、查看collections模块下的某个函数或方法的帮助文档。例如:help(collections.deque)

print(help(collections.deque))
>>>
Help on class deque in module collections:

class deque(builtins.object)
 |  deque([iterable[, maxlen]]) --> deque object
 |  
 |  A list-like sequence optimized for data accesses near its endpoints.
 |  
 |  Methods defined here:
 |  
 |  __add__(self, value, /)
 |      Return self+value.
 |  
 |  __bool__(self, /)
 |      self != 0
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __copy__(...)
 |      Return a shallow copy of a deque.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(self, key, /)
 |      Return self[key].
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __iadd__(self, value, /)
 |      Implement self+=value.
 |  
 |  __imul__(self, value, /)
 |      Implement self*=value.
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __mul__(self, value, /)
 |      Return self*value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __reduce__(...)
 |      Return state information for pickling.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __reversed__(...)
 |      D.__reversed__() -- return a reverse iterator over the deque
 |  
 |  __rmul__(self, value, /)
 |      Return value*self.
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(...)
 |      D.__sizeof__() -- size of D in memory, in bytes
 |  
 |  append(...)
 |      Add an element to the right side of the deque.
 |  
 |  appendleft(...)
 |      Add an element to the left side of the deque.
 |  
 |  clear(...)
 |      Remove all elements from the deque.
 |  
 |  copy(...)
 |      Return a shallow copy of a deque.
 |  
 |  count(...)
 |      D.count(value) -> integer -- return number of occurrences of value
 |  
 |  extend(...)
 |      Extend the right side of the deque with elements from the iterable
 |  
 |  extendleft(...)
 |      Extend the left side of the deque with elements from the iterable
 |  
 |  index(...)
 |      D.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |  
 |  insert(...)
 |      D.insert(index, object) -- insert object before index
 |  
 |  pop(...)
 |      Remove and return the rightmost element.
 |  
 |  popleft(...)
 |      Remove and return the leftmost element.
 |  
 |  remove(...)
 |      D.remove(value) -- remove first occurrence of value.
 |  
 |  reverse(...)
 |      D.reverse() -- reverse *IN PLACE*
 |  
 |  rotate(...)
 |      Rotate the deque n steps to the right (default n=1).  If n is negative, rotates left.
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  maxlen
 |      maximum size of a deque or None if unbounded
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None

01. namedtuple函数——定义一个返回值为tuple的类

(1)namedtuple 功能详解: namedtuple() 定义一个返回值为tuple的类。

(2)namedtuple语法说明: namedtuple('名称', [ 属性list])

(3)namedtuple定义的tuple类的元素访问方式: namedtuple()规定了元组的元素个数,访问类中元素的方式有两类:

  1. 使用【下标】获取元素;
  2. 使用【属性】直接获取元素。
from collections import namedtuple
User = namedtuple("Student", ["name", "age", "weight"])  # 定义类名(Student)和类的格式(包含属性:"name", "age", "weight")
user = User("admin", "20", "60")  # 实例化类
# 多变量赋值
name, age, weight = user
print(User)# 类的形式
>>>
__main__.Student
print(user)     # 实例化后的类
>>>
Student(name='admin', age='20', weight='60')
# 通过类实例的下标访问类的各个元素
print(user[0])
>>>
'admin'
print(name, age, weight)
>>>
admin 20 60
# 通过类实例的属性访问类的各个元素
print(user.name, user.age, user.weight)
>>>
admin 20 60

我们知道,Python中元组的一个重要特征就是元素不可增删改,而查找tuple元素时一般采取索引

使用namedtuple(typename, field_name)可以命名tuple中的元素,之后便可使用名字来查找tuple中的值,有点类似于字典中的查找。

from collections import namedtuple
animal = namedtuple('animal', 'name age')   # 等价于User = namedtuple("Student", ["name", "age", "weight"]),即:定义类名(Student)和类的格式
mark = animal(name='dog', age=2)
print(mark)
>>>
animal(name='dog', age=2)

namedtuple() 相当于直接定义了一个新的类,但是这个类跟传统定义 class 的方式又有着巨大区别。

  1. 该方式会比直接定义 class 的方式省很多空间;
  2. 该方式的返回值是一个 tuple,支持 tuple 的各种操作。

同时,namedtuple() 还自带两个非常好用的方法。

  • User._make(user) :将序列直接转换为新的 tuple 对象。
  • user._asdict():将tuple转化为dict对象。
# 将序列直接转换为新的 tuple 对象
user = ["root", 32, 65]
user = User._make(user) 
print(user) 
>>>
Student(name='root', age=32, weight=65)

# 将tuple转化为dict对象
user = User("admin", 20, 60)
print(user._asdict())
>>>
OrderedDict([('name', 'admin'), ('age', 20), ('weight', 60)])1)生成list-tuple型的复合的list
user =User("root", 32, 65)
user1 = User('admin', 20, 60)
cumsum_list = list()
cumsum_list.append(user1)  # 等价于cumsum_list.append(tuple(user1))
cumsum_list.append(user)
cumsum_list
>>>
[Student(name='root', age=32, weight=65),
 Student(name='root', age=32, weight=65)]
# cumsum_list外层支持list的所有操作,内层为tuple,支持tuple的所有操作
cumsum_list[0].name   # 通过属性访问元素
>>>
'root'
cumsum_list[0][0]   # 通过下标访问元素
>>>
'root'2)生成list-dict型的复合的list
user1 = User("root", 32, 65)
user2 = User("admin", 30, 60)
cumsum_list = list()
cumsum_list.append(user1._asdict())  # 等价于cumsum_list.append(dict(user1._asdict()))
cumsum_list.append(user2._asdict())
cumsum_list
>>>
[OrderedDict([('name', 'root'), ('age', 32), ('weight', 65)]),
 OrderedDict([('name', 'admin'), ('age', 30), ('weight', 60)])]
# cumsum_list支持list的所有操作,内层为dict,支持dict的所有操作
cumsum_list[0]['name']
>>>
'root'

完整应用实例:

# 定义一个圆,可通过元组对应的名字来访问圆的圆心坐标、半径。
from collections import namedtuple
circle = namedtuple("Circle", ["x", "y", "r"])
print(circle)
>>>
<class '__main__.Circle'>
# 实例化一个返回值为tuple的类
circle1 = circle(2,4,6)  # 圆心(2,4),半径6
print("实例化的圆:", circle1)
>>>
实例化的圆: Circle(x=2, y=4, r=6)
# 通过属性访问各元素值
print("circle1的圆心:",circle1.x, circle1.y)
print("circle1的半径:",circle1.r)
>>>
circle1的圆心: 2 4
circle1的半径: 6
propotion = circle1[2]*circle1[2]*3.14
print("圆的面积为:", propotion)
>>>
圆的面积为: 113.04

对于从csv或sqlite3模块返回的结果,使用_make方法将它们分配给命令数组非常有用。

Student = namedtuple('Student', 'id, name, age, className, score')

 import csv
"""
csv.reader()返回一个reader对象,利用该对象遍历csv文件中的行。 从csv文件中读取的每一行都作为字符串列表返回。
"""
 for emp in map(Student._make, csv.reader(open("students.csv", "rb"))):
     print(emp.name, emp.age)

 import sqlite3
 conn = sqlite3.connect('/studentdata')
 cursor = conn.cursor()
 cursor.execute('SELECT id, name, age, className, score FROM students')
 for emp in map(Student._make, cursor.fetchall()):
     print(emp.name, emp.age)

02. ChainMap ——将多个字典集合到一个字典,并对外提供一个统一视图

ChainMap功能详解: ChainMap() 将多个字典集合到一个字典,并对外提供一个统一视图。

注意:该操作并是不将所有字典做了一次拷贝,实际上是在多个字典的上层又进行了一次封装而已。

from collections import ChainMap

user1 = {
    
    "name":'admin', "age":20}
user2 = {
    
    "name":'root', "weight":65}
users = ChainMap(user1, user2)
print(users.maps)
>>>
[{
    
    'name': 'admin', 'age': 20}, {
    
    'name': 'root', 'weight': 65}]
# 修改【统一视图字典】中的某个元素,类似字典key-value的访问方式
users.maps[0]["name"] = "tiger"
print(users.maps)
>>>
[{
    
    'name': 'tiger', 'age': 20}, {
    
    'name': 'root', 'weight': 65}]

# 循环遍历查看【统一视图字典】的各个元素,如果 ChainMap() 中的多个字典有重复 key,查看的时候可以看到所有的 key,但遍历的时候却只会遍历 key 第一次出现的位置,其余的忽略。
for key, value in users.items():
    print(key, value)
>>>
name tiger
weight 65
age 20

如果 ChainMap() 得到的【统一视图字典】中的多个字典有重复 key时,

  • 通过users.maps查看的时候,可以看到所有的 key;
  • 通过for key, value in users.items():遍历的时候,却只会遍历 key 第一次出现的位置,其余的忽略。

同时,我们 可以通过返回的新的【统一视图字典】来更新【原来的字典】数据。进一步验证了该操作不是做的拷贝,而是直接指向原字典。

03. deque——在list两端快速【添加】或【弹出】指定元素

(1)deque功能详解: dqueue 是 ”double-ended queue” 的简称,是一种类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)操作,大大加快了遍历速度。

  1. deque([list]).append(元素):在list的右侧添加指定元素;
  2. deque([list]).appendleft(元素):在list的左侧添加指定元素;
  3. deque([list]).popleft():弹出list最左侧的元素;
  4. deque([list]).pop():弹出list最右侧的元素;
  5. deque([list]).extendleft(元素):在list的左侧添加指定元素;
  6. deque([list]).extend(元素):在list的右侧添加指定元素;
  7. deque([list]).reverse():反转队列;
  8. deque([list]).count(元素):统计某元素出现的次数;
  9. deque([list]).cleart():清空队列;
  10. deque([list]).index(元素):取得元素下标;
  11. deque([list]).insert(位置,元素):指定位置插入元素;
  12. deque([list]).maxlen:只读的属性,deque的最大长度,如果无解,就返回None;

Python中的list是基于数组实现的,所以,查找容易,但是插入和删除操作时间复杂度较大
deque就是为了高效实现插入和删除操作的双向列表,适合用于队列和栈,而且线程安全。

  • list只提供了append和pop方法来从list的尾部插入或者删除元素;
  • deque新增了appendleft/popleft等方法可以更高效的在元素的开头来插入/删除元素。

(2)deque语法说明: deque(列表), 返回值:列表

(3)deque典型范例:

from collections import deque
q = deque([1,2,3])
q.append('4')   # 在list的右侧添加元素’4‘
q.appendleft('0')  # 在list的左侧添加元素’0‘
print(q)
>>>
deque(['0', 1, 2, 3, '4'])

print(q.popleft())  # 弹出list最左侧的元素;
>>>
0
print(q)
>>>
deque([1, 2, 3, '4'])

print(q.pop())   # 弹出list最右侧的元素;
>>>
4
print(q)
>>>
deque([1, 2, 3])   # 生成的deque([1, 2, 3])类型为list,支持list的所有操作

from collections import deque
d = deque([1,2,3,4,5])
d.extendleft([0])
print(d)
>>>
deque([0, 1, 2, 3, 4, 5])

# reverse()反转队列  
d.reverse()
print(d)
>>>
deque([5, 4, 3, 2, 1, 0])
# count()计数  
print(d.count(1))  # 有该元素则返回对应的统计次数
>>>
1
print(d.count('R'))  # 无该元素则返回0
>>>
0
# clear()清空队列 
d.clear()
print(d)
>>>
deque([7, 6, 5, 4, 3, 2, 1])

# index()取得元素下标
d = deque(['a','b','c','d','e'])
print(d.index('c'))
>>>
2
# insert()指定位置插入元素  
d.insert(1,'Runsen')  
print(d) 
>>>
deque(['a', 'Runsen', 'b', 'c', 'd', 'e'])

04. Counter——统计每个元素出现的次数

(1)Counter功能详解: Counter 可以简单理解为一个计数器,可以统计每个元素出现的次数。同样地, Counter() 需要接受一个可迭代的对象(如:list)。

(2)Counter语法说明 collections.Counter(),返回值:可迭代内容的字典的Counter类。

  • Counter对象创建的四种方法:
c = Counter()   # 创建一个空的Counter类
c = Counter('gallahad')   # 从一个可iterable对象(list、tuple、dict、字符串等)创建——字符串型
c = Counter(["cat", "dog", "cat", "bird", "horse", "cat"])  # 从一个可iterable对象(list、tuple、dict、字符串等)创建——list型
c = Counter({
    
    'a': 4, 'b': 2})  # 从一个字典对象创建
c = Counter(a=4, b=2)   # 从一组键值对创建

(3)Counter返回值中元素的访问方式: Counter的返回值是一个字典,通过调用most_common() 方法,可以求得 Top k 问题,返回值为list-tuple的形式,外层与list的调用方式相同,内层与tuple的调用方式相同。

  • counter.most_common(N)将Counter按照value从大到小排列,获取前N个元素。
  • counter.elements()取得计数器中的所有元素。
  • sorted(counter)将Counter中的key进行排序,返回的是所有key的列表。
  • ''.join(counter.elements())将Counter转换成字符串。
  • counter.update(collections.Counter('a'))更新计数器,其实在原本的counter基础上更新计数器,如果原来没有该key,则新建key,如果有该key则,在该key的value基础上加1。
  • counter.subtract('abdabcabcg') 相减计数器的values,即原来的计数器中的每一个元素的数量减去后添加的元素的数量。
  • sum(c.values()):统计所有的数目;
  • list(c):列出所有唯一的元素;
  • set(c):转换为set;
  • dict(c) :转换为常规的dict;
  • c.items():转换为(elem,cnt)对构成的列表;
  • c.most_common()[:-4:-1]:输出n个数目最小元素;
  • c += Counter():删除数目为0和为负的元素;
  • Counter(dict(c.items())):从(elem,cnt)对构成的列表转换为counter;
  • c.clear():清空counter;
  • c.total():计算总计数值。

对Counter对象进行数学操作,得到多集合(counter中元素数目大于0)

  • 加法和减法操作,是相加或者相减对应元素的数目
  • 交集和并集返回对应数目的最小值和最大值

每个操作均接受的是所有有符号的数目,但是输出并不包含数目为0或者为负的元素;

# Counter用来统计各个值出现的次数——【字符串序列】
from collections import Counter
c = Counter('abcdeabcdabcaba')
print(c)
>>>
Counter({
    
    'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})
b = dict(c)
print(b)
>>>
{
    
    'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1}
print(b['name'])
>>>
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'name'
print(c['name'])
>>>
0
# elements()取得计数器中的所有元素。
print(counter.elements()) 
# 输出如下 
<itertools.chain object at 0x0000025B1477BF98> 
print(list(c.elements()))  # 需要用list转化为可读的list元素集列表
>>>
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']
# update()更新计数器
g = collections.Counter('agd')
print(g)
>>>
Counter({
    
    'a': 1, 'g': 1, 'd': 1})
c.update(g)
print(c)
>>>
Counter({
    
    'a': 6, 'b': 4, 'c': 3, 'd': 3, 'e': 1, 'g': 1})
# subtract()相减计数器的values,即原来的计数器中的每一个元素的数量减去后添加的元素的数量
c.subtract('abdda')
print(c)
>>>
Counter({
    
    'a': 4, 'b': 3, 'c': 3, 'd': 1, 'e': 1, 'g': 1})

# Counter用来统计各个值出现的次数——【字符串list】
from collections import Counter
animals = ["cat", "dog", "cat", "bird", "horse", "tiger", "horse", "cat"]
animals_counter = Counter(animals)
print(animals_counter)
>>>
Counter({
    
    'cat': 3, 'horse': 2, 'dog': 1, 'bird': 1, 'tiger': 1})

print(animals_counter.most_common(2))
>>>
[('cat', 3), ('horse', 2)]
或者
from collections import Counter

test_counter_data = ["cat", "dog", "cat", "bird", "horse", "tiger", "horse", "cat"]
counter_data = Counter()
for item in test_counter_data:
    counter_data[item] += 1
print(counter_data)
>>>
Counter({
    
    'cat': 3, 'horse': 2, 'dog': 1, 'bird': 1, 'tiger': 1})

等价于
counter_data = Counter(test_counter_data)
print(counter_data)
>>>
Counter({
    
    'cat': 3, 'horse': 2, 'dog': 1, 'bird': 1, 'tiger': 1})

如何实现按照词频顺序对单词进行排序

from collections import Counter
test_counter_data = ["cat", "dog", "cat", "bird", "horse", "tiger", "horse", "cat"]
counter_data = Counter(test_counter_data)
print(counter_data)
# 按照词频顺序对单词进行排序
import operator
sorted_word_to_cnt = sorted(counter_data.items(),key = operator.itemgetter(1),reverse = True)
print(sorted_word_to_cnt)

上述示例说明:Counter(test_counter_data_list)等价于

for item in test_counter_data_list:
    counter_data[item] += 1

因此,代码段大大缩减。

完整范例:

c = Counter(a=4,b=2,c=0,d=-2)
print(c)
>>>
Counter({
    
    'a': 4, 'b': 2, 'c': 0, 'd': -2})
sum(c.values())# 统计所有的数目
>>>
4
list(c)# 列出所有唯一的元素
>>>
['a', 'b', 'c', 'd']
set(c)# 转换为set
>>>
{
    
    'a', 'b', 'c', 'd'}
dict(c)# 转换为常规的dict
>>>
{
    
    'a': 4, 'b': 2, 'c': 0, 'd': -2}
c.items()# 转换为(elem,cnt)对构成的列表
>>>
dict_items([('a', 4), ('b', 2), ('c', 0), ('d', -2)])
c.most_common()[:-4:-1]# 输出n个数目最小元素
>>>
[('d', -2), ('c', 0), ('b', 2)]
c += Counter()# 删除数目为0和为负的元素
print(c)
>>>
Counter({
    
    'a': 4, 'b': 2})
Counter(dict(c.items()))# 从(elem,cnt)对构成的列表转换为counter
>>>
Counter({
    
    'a': 4, 'b': 2})
c.clear()# 清空counter
print(c)
>>>
Counter()
# Counter对象进行数学操作
c = Counter(a=3,b=1,c=-2)
print(c)
>>>
Counter({
    
    'a': 3, 'b': 1, 'c': -2})
d = Counter(a=1,b=2,c=4)
print(d)
>>>
Counter({
    
    'c': 4, 'b': 2, 'a': 1})
"""在Counter对象进行数学操作,得多集合(counter中元素数目大于0)加法和减法操作,是相加或者相减对应元素的数目;
交集和并集返回对应数目的最小值和最大值;
每个操作均接受的是有符号的数目,但是输出并不包含数目为0或者为负的元素;"""
c+d#求和
>>>
Counter({
    
    'a': 4, 'b': 3, 'c': 2})
c-d#求差
>>>
Counter({
    
    'a': 2})
c & d#求交集
>>>
Counter({
    
    'a': 1, 'b': 1})
c | d#求并集
>>>
Counter({
    
    'a': 3, 'b': 2, 'c': 4})

05. OrderedDict——保证了元素的插入顺序

(1)OrderedDict 功能详解: OrderedDict 是字典的子类,保证了元素的插入顺序。

(1)在Python3.6之前的字典是无序的,但是有时候我们需要保持字典的有序性,orderDict可以在dict的基础上实现字典的有序性,这里的有序指的是按照字典key插入的顺序来排列,这样就实现了一个先进先出的dict,当容量超出限制时,先删除最早添加的key。
(2)在Python3.7 版本下,字典同样也保证了元素的插入顺序。那相比内置字典 OrderedDict 有哪些升级呢。

  • 算法上, OrderedDict 可以比 dict 更好地处理频繁的重新排序操作。在跟踪最近的访问这种场景(例如在 LRU cache)下非常适用。
  • OrderedDict 类有一个 move_to_end() 方法,可以有效地将元素移动到任一端。

(2)OrderedDict 常见属性:

  1. dic.keys():获得字典的所有键 ;
  2. dic.values():获得字典的所有值;
  3. dic.items():以列表返回可遍历的(键, 值) 元组数组;
  4. dic.pop(键):删除指定的键值;
  5. dic.popitem()方法,默认删除字典最后一个元素;
  6. dic.update({'k1':'v1111','k10':'v10'}):更新字典;
  7. dict.move_to_end(键):将元素移动到末尾;
from collections import OrderedDict

user = OrderedDict()
user["name"] = "admin"
user["age"] = 23
user["weight"] = 65
print(user)
>>>
OrderedDict([('name', 'admin'), ('age', 23), ('weight', 65)])

user.move_to_end("name")   # 将元素移动到末尾
print(user)
>>>
OrderedDict([('age', 23), ('weight', 65), ('name', 'admin')])
# 字典所有的键
user.keys()
>>>
odict_keys(['name', 'age', 'weight'])
# 字典所有值  
print(user.values()) 
>>>
odict_values(['admin', 23, 65])
# items() 方法以列表返回可遍历的(键, 值) 元组数组  
print(dic.items()) 
>>>
odict_items([('name', 'admin'), ('age', 23), ('weight', 65)])
#pop()方法,删除指定的键值  
user.pop('name')
print(user)
>>>
OrderedDict([('age', 23), ('weight', 65)])
#popitem()方法,默认删除字典最后一个元素  
user.popitem()  
print(user)
>>>
OrderedDict([('age', 23)])
# update()更新字典  
user.update({
    
    'k1':'v1111','k10':'v10'})  
print(user)
>>>
OrderedDict([('age', 23), ('k1', 'v1111'), ('k10', 'v10')])

user.move_to_end("name", last=False)   # 将元素移动到开头
print(user)
>>>
OrderedDict([('name', 'admin'), ('age', 23), ('weight', 65)])

原始的字典定义和通过OrderedDict()定义字典的用法区别的示例:

original_dict = {
    
    'a':2, 'b':4, 'c':5}
for key, value in original_dict.items():
    print(key,value)
>>>
a 2
b 4
c 5
# OrderedDict是按照字典创建时的插入顺序来排序的。
original_dict = OrderedDict([('a',2), ('b',4), ('c',5)])
for key, value in original_dict.items():
    print(key, value)
>>>
a 2
b 4
c 5

06. defaultdict——内置 dict 类的子类,实现了当 key 不存在时返回默认值的功能

(1)defaultdict 功能详解: defaultdict 是内置 dict 类的子类,它实现了当 key 不存在时返回默认值的功能,除此之外,与内置 dict 功能完全一样。

(2)defaultdict 语法说明: collections.defaultdict(函数),​返回值:返回括号里的函数。

(3)defaultdict 典型范例:

"""
这个类似于我们使用​:try...except...这个关键字的用法
"""
d1 = {
    
    "one":1,"two":2,"three":3}
print(d1["four"])
>>>
KeyError: 'four'
#上面的会报错,下面的就会返回函数,告诉我们错了
func = lambda:"错了"
d2 = collections.defaultdict(func)
d2['one']=1
d2['two']=2
print(d2['four'])
>>>
错了

from collections import defaultdict
default_dict = defaultdict(int)
default_dict['x'] = 10
print(default_dict['x'])
>>>
10
print(default_dict['y'])
>>>
0

给 defaultdict 传了一个自定义函数,实现当字典中不存在所取 key 时返回默认的用户信息。

def getUserInfo():
    return{
    
    
        "name":'默认name',
        "age":0,
    }
default_dict = defaultdict(getUserInfo)
admin = default_dict["admin"]  # 访问dict不存在的key="admin"时,返回默认值
print(admin)
>>>
{
    
    'name': '默认name', 'age': 0}
# 通过键值对访问,修改指定key的value
admin["age"] = 34
print(admin)
>>>
{
    
    'name': '默认name', 'age': 34}
  • defaultdict(list) :定义defaultdict字典的value值的type为list类型
  • defaultdict(int) :定义defaultdict字典的value值的type为int类型
from collections import defaultdict

test_data = (('cat',2),('dog',5),('sheep',3),('cat',1),('sheep',6))
print(type(test_data))
>>>
<class 'tuple'>
test_data_dict = defaultdict(list)  # 定义defaultdict字典的value值的type为list类型
print(test_data_dict)
>>>
defaultdict(<class 'list'>, {
    
    })
for name, num in test_data:
    test_data_dict[name].append(num)
print(test_data_dict)
>>>
defaultdict(<class 'list'>, {
    
    'cat': [2, 1], 'dog': [5], 'sheep': [3, 6]})
# defaultdict为一个dict-list的复合型,外层访问与dict一致,内层访问与list一致。
print(test_data_dict['cat'])
>>>
[2, 1]

参考链接:

Python中的collections模块

Python collections模块使用方法详解

深入Python中的 Collections 模块

python collections模块详解

廖雪峰的官方网站:collections

Python官方教程:collections — 容器数据类型¶

猜你喜欢

转载自blog.csdn.net/weixin_42782150/article/details/127295703