跳转到主要内容
模块 8 · 第 3 课(共 4)课程中的31/36~12 min
模块课程(3/4)

集合:Counter 和 defaultdict

collections 模块添加了专门的数据类型来扩展 内置集合。最常用的三个:Counter、defaultdict、 namedtuple。

Counter:频率计数

Python
from collections import Counter

parole = ["mela", "pera", "mela", "kiwi", "mela", "pera"]
c = Counter(parole)
# Counter({'mela': 3, 'pera': 2, 'kiwi': 1})

c["mela"]            # 3
c["banana"]          # 0   (default for missing keys, NO KeyError)
c.most_common(2)     # [('mela', 3), ('pera', 2)]

它也适用于字符串(计算字符数):

Python
Counter("ciao mondo")
# Counter({'o': 2, 'c': 1, 'i': 1, 'a': 1, ' ': 1, 'm': 1, 'n': 1, 'd': 1})

它支持类似集合的计数操作(+、-、&、|)——非常方便 用于聚合来自不同来源的计数。

defaultdict:具有自动默认值的字典

一个字典,当您访问丢失的密钥时,通过调用创建它 工厂。

Python
from collections import defaultdict

gruppi = defaultdict(list)        # factory = list (empty list)
for nome in ["Ada", "Linus", "Ada", "Grace"]:
    gruppi[nome].append(1)
# defaultdict(list, {'Ada': [1, 1], 'Linus': [1], 'Grace': [1]})

如果没有 defaultdict,您必须编写:

Python
gruppi = {}
for nome in [...]:
    if nome not in gruppi:
        gruppi[nome] = []
    gruppi[nome].append(1)

常见工厂:list、int(默认0)、set、dict。

namedtuple:具有字段名称的元组

创建不可变记录类的轻量级方法。它是一个元组,但是 通过名称进行字段访问。

Python
from collections import namedtuple

Punto = namedtuple("Punto", ["x", "y"])
p = Punto(3, 4)
p.x          # 3 (access by name)
p[0]         # 3 (access by index, still a tuple)
p.x + p.y    # 7

# typical use: return multiple values from a function
def divisione(a, b):
    Risultato = namedtuple("Risultato", ["quoziente", "resto"])
    return Risultato(a // b, a % b)

r = divisione(17, 5)
r.quoziente   # 3
r.resto       # 2

(对于更复杂的情况,自 3.7 起还有 dataclasses — 请参阅 M9。)

nametuple:轻量级不可变记录

collections 模块还导出 namedtuple,它允许您快速构建轻量级类对象来存储结构化数据,而无需编写构造函数或样板方法:

Python
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y)

尝试一下

锻炼#python.m8.l3.e1
尝试:0加载中...

给定列表 `words = ['mela', 'pera', 'mela', 'kiwi', 'mela', 'pera']`,将 `top` 中最常见的单词计算为字符串。评估“顶部”。

正在加载编辑器...
显示提示

Counter(...).most_common(1) 返回 [(word, count)]。

3 次尝试后可用的解决方案

复习练习

锻炼#python.m8.l3.e2
尝试:0加载中...

给定学生 `enrollments = [('Ada', 'mate'), ('Linus', 'fisica'), ('Ada', 'storia'), ('Grace', 'mate')]`,将 `courses_per_student` 构建为 defaultdict(list)。评估`dict(courses_per_student)`。

正在加载编辑器...
显示提示

defaultdict(list) 然后用于注册中的 s、c。

3 次尝试后可用的解决方案

额外的挑战

锻炼#python.m8.l3.e3
尝试:0加载中...

从“集合”导入“计数器”。计算字符串 \`text = "abracadabra"\` 中字符的频率。将计数器存储在“char_counter”中并对其进行评估。

正在加载编辑器...
显示提示

Counter 将字符串作为参数并计算每个字母的出现次数。

3 次尝试后可用的解决方案