Python dataclasses 中 field 的 default_factory 参数用法
flyfish
default_factory 有一个规则 :
必须传给它一个 函数,不能传给它一个 值
而且这个函数必须是 无参函数(不需要传任何参数)
无参函数 = 定义时括号里没有参数 ,调用时也不用传值 的函数
格式:
python
def 函数名():
return 默认值
default_factory 的工作流程:
- 给它一个无参函数
- 每次创建对象时,它会自动调用这个函数(不加参数)
- 用函数的返回值作为属性的默认值
list / dict / set 不只是可变类型,它们本身就是 Python 内置的无参函数
符合 default_factory 必须传无参函数的要求。
无参函数
- 平时写
[]是空列表,等价于调用函数list() list()是一个无参函数 ,调用就返回一个新的空列表- 同理:
dict()→ 无参函数 → 返回新空字典{}
set()→ 无参函数 → 返回新空集合set()
这些数据类型的名字,本身就是构造函数
以下3 种写法完全一模一样
1. 直接传 list
python
from dataclasses import dataclass, field
@dataclass
class Student:
scores: list = field(default_factory=list) # list 是无参函数
2. 自定义无参函数写法
python
def create_list():
return []
@dataclass
class Student:
scores: list = field(default_factory=create_list)
3. lambda 简写写法
python
@dataclass
class Student:
scores: list = field(default_factory=lambda: [])
例子
cpp
# 导入必需的库
from dataclasses import dataclass, field
from pathlib import Path
# ==============================================
# 写法 1:使用 lambda
# ==============================================
@dataclass
class AppConfig1:
# 无参 lambda:满足 default_factory 要求
IMG_STORAGE_ROOT: Path = field(default_factory=lambda: Path("data/img_history"))
# ==============================================
# 写法 2:去掉 lambda → 用普通无参函数实现
# ==============================================
# 1. 定义一个 无参函数(括号为空!)
def create_img_path():
# 函数内部调用 Path,传入路径参数
return Path("data/img_history")
@dataclass
class AppConfig2:
# 2. 把无参函数传给 default_factory
# 不能加括号 写 create_img_path 不是 create_img_path()
IMG_STORAGE_ROOT: Path = field(default_factory=create_img_path)
# ==============================================
# 测试:两种写法效果完全相同
# ==============================================
if __name__ == '__main__':
# 测试 lambda 版本
config1 = AppConfig1()
print("带lambda的结果:", config1.IMG_STORAGE_ROOT)
# 测试 无lambda 普通函数版本
config2 = AppConfig2()
print("不带lambda的结果:", config2.IMG_STORAGE_ROOT)
# 验证:两个对象都是独立的(符合default_factory规则)
print("两个路径对象是否独立:", config1.IMG_STORAGE_ROOT is not config2.IMG_STORAGE_ROOT)
结果
带lambda的结果: data\img_history
不带lambda的结果: data\img_history
两个路径对象是否独立: True
lambda 是无参的(lambda: 后面没有参数),"data/img_history" 是传给 Path() 的参数,不是传给 lambda 的
-
不加括号
create_img_path→ 代表函数本身 (把这个函数当成工具,传递过去 )这是 default_factory 唯一要的东西
-
加括号
create_img_path()→ 代表调用函数,拿到返回值 (直接执行函数,把结果传过去) default_factory 不要这个!
python
from dataclasses import dataclass, field
from pathlib import Path
# 无参函数
def create_img_path():
return Path("data/img_history")
@dataclass
class AppConfig:
# 不加括号!!!传的是【函数本身】
IMG_STORAGE_ROOT: Path = field(default_factory=create_img_path)
执行流程 :
创建对象 config = AppConfig() → dataclass 自动调用这个函数 → 生成新的Path
错误写法:加括号(传返回值)
python
@dataclass
class AppConfig:
# 加括号!!!直接执行函数,传的是【Path对象】
IMG_STORAGE_ROOT: Path = field(default_factory=create_img_path())
直接报错
因为 default_factory 要函数 ,却给了它一个Path值。