dataclass装饰器
dataclasses模块的三个重要函数:
- dataclass:类的装饰器函数,自动生成数据类的各种魔术方法
- field:用于精细控制每个字段的行为
- fields:用于获取类的字段
后边写数据类的时候用一用这种写法,看看和传统写法相比到底能不能让结构更清晰,更省代码量,一个例子:
利用dataclasses模块提供的函数创建纯数据类from dataclasses import dataclass, field, fields from typing import List @dataclass class Config: api_key: str timeout: int = field(default=30, metadata={"unit": "seconds"}) retry_count: int = 3 endpoints: List[str] = field(default_factory=list) config = Config(api_key="abc123") print(fields(config))
设置属性默认值的坑
Python 语言的基本规则:函数的默认参数在定义时(而非调用时)被求值。对于可变参数例如列表直接设置属性为[]会使得生成的所有实例的对应属性是同一个[]。
from dataclasses import dataclass
@dataclass
class Wrong:
name: str
items: list = [] # 默认值是 [] 字面量
# 创建两个实例
w1 = Wrong("张三")
w2 = Wrong("李四")
# 只给 w1 添加元素
w1.items.append(1)
print(w1.items) # 输出:[1]
print(w2.items) # 输出:[1] ← 惊不惊喜?李四的列表也被改了!
在普通函数/类中,标准解法是使用 None 做哨兵值,在函数体内部新建列表:
# 普通类/函数的标准安全写法
def add_item(item, lst=None):
if lst is None:
lst = [] # 每次调用都新建列表
lst.append(item)
return lst
print(add_item(1)) # 输出:[1]
print(add_item(2)) # 输出:[2] ← 完美独立!
@dataclass 里的field(default_factory=list),本质上就是 Python 官方把这套 None + 判断的模板代码,封装成了更优雅、语义更清晰的写法。写成feild(default_factory=list)就OK了,它告诉解释器不要用现有的对象,请在__init__运行时执行 list() 工厂函数取返回值。
参考:https://docs.pythonlang.cn/3/library/dataclasses.html
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.
Comments





