0
点赞
收藏
分享

微信扫一扫

collections --- 容器数据类型

Sky飞羽 2022-03-27 阅读 76
python

目录


这个模块实现了特定目标的容器,以提供Python 标准内建容器dict , list , set , 和tuple 的替代选择

ChainMap 对象

  • ChainMap 非常强大的dict字典组合功能,他将多个dict字典放入到一个list中,他比dict字典使用update快很多。通过ChainMap可以来模拟嵌套的情景,而且多用于模板之中
from collections import ChainMap

m1 = {'Type': 'admin', 'codeID': '00001'}
m2 = {'name': 'woodname', 'codeID': '00002'}
m = ChainMap(m1, m2)
print(m)
# 输出:
# ChainMap({'Type': 'admin', 'codeID': '00001'}, {'name': 'woodname', 'codeID': '00002'})

print(m.maps)
# 输出:[{'Type': 'admin', 'codeID': '00001'}, {'name': 'woodname', 'codeID': '00002'}]

for i in m.items():
    print(i)
# 输出:
# ('name', 'woodname')
# ('codeID', '00001')
# ('Type', 'admin')

print(m['name'])  # 读取元素的值
print(m['codeID'])  # 注意,当key重复时以最前一个为准
print(m.get('Type'))
# 输出:
# woodname
# 00001
# admin

# 新增map
m3 = {'data': '888'}
m = m.new_child(m3)  # 将 m3 加入m
print(m)
# 输出:
# ChainMap({'data': '888'}, {'Type': 'admin', 'codeID': '00001'}, {'name': 'woodname', 'codeID': '00002'})

print(m.parents)  # m 的父亲
# 输出:ChainMap({'Type': 'admin', 'codeID': '00001'}, {'name': 'woodname', 'codeID': '00002'})

print(m.parents.parents)
# 输出 : ChainMap({'name': 'woodname', 'codeID': '00002'})

Counter 对象

class collections.Counter([iterable-or-mapping ])

  • 一个Counter 是一个dict 的子类,用于计数可哈希对象。它是一个集合,元素像字典键(key) 一样存储,它们的计数存储为值。计数可以是任何整数值,包括0 和负数。
  • 创建一个 Counter:
from collections import Counter

c = Counter()  # 创建一个新的空counter
c = Counter('abcasdf')  # 一个迭代对象生成的counter
c = Counter({'red': 4, 'yello': 2})  # 一个映射生成的counter
c = Counter(cats=2, dogs=5)  # 关键字参数生成的counter

# counter 生成counter, 虽然这里并没有什么用
c = Counter('abcasd')
print(c)  # Counter({'a': 2, 'c': 1, 'b': 1, 's': 1, 'd': 1})
c2 = Counter(c)
print(c2) # Counter({'a': 2, 'c': 1, 'b': 1, 's': 1, 'd': 1})
  • 因为 Counter 实现了字典的 missing 方法, 所以当访问不存在的key的时候,返回值为0:
from collections import Counter

c = Counter(['apple', 'pear'])
print(c['orange']) # 0

设置一个计数为0 不会从计数器中移去一个元素。使用del 来删除它:

>>> c['sausage'] = 0 
>>> del c['sausage']

elements()

  • 按照counter的计数,重复返回元素
from collections import Counter

c = Counter(a=4, b=2, c=0, d=-2)
print(list(c.elements()))

most_common([n ])

  • 按照counter的计数,按照降序,返回前n项组成的list; n忽略时返回全部
from collections import Counter

c = Counter('abracadabra')
print(c)
print(c.most_common(3))

subtract([iterable-or-mapping ])

  • counter按照相应的元素,计数相减
from collections import Counter

c = Counter(a=4, b=2, c=0, d=-2)
d = Counter(a=1, b=2, c=3, d=4)
c.subtract(d)
print(c)  # Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})

total()

  • 计算总计数值,3.10 新版功能.
>>> c = Counter(a=10, b=5, c=0)
>>> c.total()
15

update([iterable-or-mapping ])

  • update([iterable-or-mapping])不同于字典的update方法,这里更新counter时,相同的key的value值相加而不是覆盖
import collections

x1 = collections.Counter({'a': 1, 'b': 2})
x2 = collections.Counter(a=1, b=2)
x1.update(x2)  # Counter()类型 isinstance(iterable, Mapping) 也返回 True

# 或者这样调用
x1 = collections.Counter({'a': 1, 'b': 2})
x1.update('aab')
print(x1)  # Counter({'a': 3, 'b': 3})

Counter 间的数学集合操作

>>> c = Counter(a=3, b=1, c=5)
>>> d = Counter(a=1, b=2, d=4)
>>> c + d                       # counter相加, 相同的key的value相加
Counter({'c': 5, 'a': 4, 'd': 4, 'b': 3})
>>> c - d                       # counter相减, 相同的key的value相减,只保留正值得value
Counter({'c': 5, 'a': 2})
>>> c & d                       # 交集:  取两者都有的key,value取小的那一个
Counter({'a': 1, 'b': 1})
>>> c | d                       # 并集:  汇聚所有的key, key相同的情况下,取大的value
Counter({'c': 5, 'd': 4, 'a': 3, 'b': 2})

常见做法:

sum(c.values())                 # 继承自字典的.values()方法返回values的列表,再求和
c.clear()                       # 继承自字典的.clear()方法,清空counter
list(c)                         # 返回key组成的list
set(c)                          # 返回key组成的set
dict(c)                         # 转化成字典
c.items()                       # 转化成(元素,计数值)组成的列表
Counter(dict(list_of_pairs))    # 从(元素,计数值)组成的列表转化成Counter
c.most_common()[:-n-1:-1]       # 最小n个计数的(元素,计数值)组成的列表
c += Counter()                  # 利用counter的相加来去除负值和0的值

deque 对象

  • list 列表 存储数据时,使用索引访问元素时很快,但插入和删除元素很慢,因为 list 列表 是线性存储数据,数据量越大插入和删除的效率越低。
  • deque 为双向列表,它能高效实现插入和删除操作。
from collections import deque

# append
# appendleft
dlist = deque([1, 'a'])
dlist.append('b')  # 在末尾加数据
dlist.appendleft(0)  # 在最前端插入数据
print(dlist)  # 输出 :  deque([0, 1, 'a', 'b'])

# pop
# popleft
dlist.pop()  # 删除末尾的数据
dlist.popleft()  # 删除最前端的数据
print(dlist)  # 输出 :  deque([1, 'a'])

# extend
# extendleft
dlist.extend(['b', 'c'])  # 在末尾追加list 数据
dlist.extendleft([-1, 0])  # 在前端插入list 数据
print(dlist)  # 输出 : deque([0, -1, 1, 'a', 'b', 'c'])

# index
print(dlist.index('a'))  # 找出 a 的索引位置 # 输出 :  3

# insert
dlist.insert(2, 555)  # 在索引2 的位置插入555
print(dlist)  # 输出 :  deque([0, -1, 555, 1, 'a', 'b', 'c'])

# count
print(dlist.count('a'))  # 查找 ‘a’ 的数量

# remove
dlist.remove(1)  # 删除第一个匹配值

# reverse
dlist.reverse()  # 反向
print(dlist)  # 输出 :  deque(['c', 'b', 'a', 555, -1, 0])

# rotate 将右端的元素移动到左端。如果n是负数,就将左端的元素移动到右端
dlist.rotate(-2)  # 将左端的元素移动到右端
print(dlist)  # 输出 :  deque(['a', 555, -1, 0, 'c', 'b'])

dlist.rotate(2)  # 将右端的元素移动到左端
print(dlist)  # 输出 :  deque(['c', 'b', 'a', 555, -1, 0])

# copy
dl1 = dlist  # 赋值 dlist 值变化,dl1的值也会修改
dl2 = dlist.copy()  # 拷贝 dlist, 拷贝后对dl修改不影响dlist的值
dlist.pop()  # 删除最后一个数据, dl1的值也被修改
print(dl1)  # 输出: deque(['c', 'b', 'a', 555, -1])
print(dl2)  # 输出: deque(['c', 'b', 'a', 555, -1, 0])

# clear
d = deque()
d.append(1)
d.clear()
print(d)  # deque([])

# maxlen
# Deque 的最大尺寸,如果没有限定的话就是None 。
d.maxlen(5)

defaultdict 对象

当我使用普通的字典时,用法一般是dict={},添加元素的只需要dict[element] =value即,调用的时候也是如此,dict[element] = xxx,但前提是element字典里,如果不在字典里就会报错,如:

dict = {'a':1}
print(dict['b'])
"""
Traceback (most recent call last):
  File "C:\Users\Desktop\新建文件夹\q.py", line 2, in <module>
    print(dict['b'])
KeyError: 'b'
"""

这时defaultdict就能排上用场了,defaultdict的作用是在于,当字典里的key不存在但被查找时,返回的不是keyError而是一个默认值
defaultdict接受一个工厂函数作为参数,如下来构造:

dict =defaultdict( factory_function)

这个factory_function可以是list、set、str等等,作用是当key不存在时,返回的是工厂函数的默认值,比如list对应[ ],str对应的是空字符串,set对应set( ),int对应0,如下举例:

from collections import defaultdict

dict1 = defaultdict(int)
dict2 = defaultdict(set)
dict3 = defaultdict(str)
dict4 = defaultdict(list)
dict1[2] ='two'

print(dict1[1])
print(dict2[1])
print(dict3[1])
print(dict4[1])
"""
输出:
0
set()

[]

"""

namedtuple() 命名元组的工厂函数

collections.namedtuple

  • collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
  • 使用实例:
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(11,y=2)
print(p[0] + p[1])
a,b = p
print(a,b)
print(p.x + p.y)
print(p)

例子2:

import collections

Person = collections.namedtuple('Person', 'name age gender')
Bob = Person(name='Bob', age=30, gender='male')
Jane = Person(name='Jane', age=29, gender='female')
print('Field by Name:', Jane.name)
for people in [Bob, Jane]:
    print("%s is %d years old %s" % people)
"""
Field by Name: Jane
Bob is 30 years old male
Jane is 29 years old female
"""

实际应用:

  • 命名元组尤其有用于赋值csv sqlite3 模块返回的元组
from collections import namedtuple

EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
import csv
for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
    print(emp.name, emp.title)
  • 赋值数据库返回
from collections import namedtuple

EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
import sqlite3
conn = sqlite3.connect('/companydata')
cursor = conn.cursor()
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
for emp in map(EmployeeRecord._make, cursor.fetchall()):
    print(emp.name, emp.title)

classmethod somenamedtuple._make(iterable)

  • 类方法从存在的序列或迭代实例创建一个新实例
>>> t = [11, 22]
>>> Point._make(t)
Point(x=11, y=22)

somenamedtuple._asdict()

  • 返回一个新的dict ,它将字段名称映射到它们对应的值
>>> p = Point(x=11, y=22)
>>> p._asdict()
{'x': 11, 'y': 22}

somenamedtuple._replace(**kwargs)

  • 返回一个新的命名元组实例,并将指定域替换为新的值
>>> p = Point(x=11, y=22)
>>> p._replace(x=33)
Point(x=33, y=22)

somenamedtuple._fields

  • 字符串元组列出了字段名。用于提醒和从现有元组创建一个新的命名元组类型。
>>> p._fields 
('x', 'y')
>>> Color = namedtuple('Color', 'red green blue')
>>> Pixel = namedtuple('Pixel', Point._fields + Color._fields)
>>> Pixel(11, 22, 128, 255, 0)
Pixel(x=11, y=22, red=128, green=255, blue=0)

somenamedtuple._field_defaults

  • 字典将字段名称映射到默认值。
from collections import namedtuple

Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
print(Account._field_defaults)  # {'balance': 0}
print(Account('premium'))  # Account(type='premium', balance=0)
举报

相关推荐

0 条评论