Python dataclasses 中 field 的 default_factory 参数用法

Python dataclasses 中 field 的 default_factory 参数用法

flyfish

default_factory 有一个规则 :
必须传给它一个 函数,不能传给它一个 值

而且这个函数必须是 无参函数(不需要传任何参数)

无参函数 = 定义时括号里没有参数 ,调用时也不用传值 的函数

格式:

python 复制代码
def 函数名():
    return 默认值

default_factory 的工作流程:

  1. 给它一个无参函数
  2. 每次创建对象时,它会自动调用这个函数(不加参数)
  3. 用函数的返回值作为属性的默认值

list / dict / set 不只是可变类型,它们本身就是 Python 内置的无参函数

符合 default_factory 必须传无参函数的要求。

无参函数

  1. 平时写 [] 是空列表,等价于调用函数 list()
  2. list() 是一个无参函数 ,调用就返回一个新的空列表
  3. 同理:
    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 的

  1. 不加括号 create_img_path

    → 代表函数本身 (把这个函数当成工具,传递过去 )这是 default_factory 唯一要的东西

  2. 加括号 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值。

相关推荐
happylifetree2 小时前
Python70:核心语法-函数进阶-案例2
python
王中阳Go3 小时前
两个入口答案不一致先别调模型:6 行入口口径对账表(附脚本)
人工智能·后端·python·大语言模型·1024程序员节
BK贝壳3 小时前
bool-hybrid-array 落盘我只认 .bha:用 Create_BHA / Ask_BHA 做布尔数组序列化
数据结构·python·numpy·1024程序员节
Sakura_j_h_4 小时前
Python 在定时任务里输出 emoji,UnicodeEncodeError 从哪来
开发语言·字符编码·windows·python·定时任务
supabc1235 小时前
欧盟电子发票(XRechnung/Peppol/ZUGFeRD)踩坑记:用 Python 不装 Java 跑官方校验规则
xml·python·开源·电子发票·1024程序员节
ZhengEnCi5 小时前
AI Agent工具调用防护层怎么写-一份能直接跑的Python四层拦截实现
python·llm·agent
ZhengEnCi6 小时前
AI Agent工具误调用怎么解决-从参数校验到高危二次确认的四层工程防线
python·llm·agent
镜子AI7 小时前
镜子AI工程教程:用Python实现关键词布局检查器与语义改写查重(附完整代码)
人工智能·python·microsoft
小oo呆8 小时前
【学习心得】Python协程
python
信誓旦旦的程序猿8 小时前
【Python量化实战宝典 #22】涨跌停、连板情绪手册:情绪指标构建(Python 可跑)
python·1024程序员节·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口