WMX · 随记
·Python· 3 分钟阅读

dataclass 默认工厂:每个实例有自己的容器

订单、任务和配置对象经常带一个列表字段。如果多个实例共享同一容器,对其中一个实例的修改就会污染其他实例。

▶ 本文含视频讲解
▶ 教学视频手动播放 · 英语讲解

Learn Python — Full Course for Beginners

Python 入门课程作为语法与编程背景复习;本文使用的较新标准库特性不保证在该课程中逐项覆盖。此为外部原版课程,多篇笔记可能共用;未剪辑为本文专属视频。

播放器需要能访问 YouTube 的网络;若这里无法加载,可打开原视频。本文与本地图解仍可独立阅读。

Python 系列概览:输入校验、数据处理与行为验证
Python 系列概览:输入校验、数据处理与行为验证 点击图片查看大图 ↗

问题从哪里出现

订单、任务和配置对象经常带一个列表字段。如果多个实例共享同一容器,对其中一个实例的修改就会污染其他实例。

理解核心机制

field(default_factory=list) 在创建实例且未提供该参数时调用工厂。它表达的是每次构造一个新默认值,区别于在类定义时求值的单个对象。

动手做一个小实验

Python 3.11 或更新版本,仅使用标准库;将示例保存为 demo.py 后执行 python3 demo.py。

Python10 行 · 可横向滚动
from dataclasses import dataclass, field
@dataclass
class Task:
    name: str
    tags: list[str] = field(default_factory=list)

a, b = Task("a"), Task("b")
a.tags.append("urgent")
assert b.tags == []
print(a, b)

适用边界与常见误区

frozen=True 也不能冻结列表内部内容。传入同一个外部列表仍会共享引用,需要根据接口承诺决定是否复制或改用 tuple。

继续练习

给两个实例显式传入同一个列表,与省略参数的情况比较;再设计一个不可变标签元组版本。

参考资料

阅读相关官方文档或原始资料 ↗

← 返回文章归档