整体说明
- 在 Python 中,
field主要关联两个核心场景:- 一是标准库
dataclasses模块的field()函数 ,用于定制数据类字段 - 二是第三方库如
pydantic的Field类 (注意:首字母是大写), 用于数据校验/序列化
- 一是标准库
dataclasses.field()
dataclasses是 Python 内置的轻量级数据类工具field()用于精细化定义数据类的字段(替代默认的简单赋值),支持定制默认值、初始化行为、序列化等- 注:Python 3.7+ 内置
dataclasses.field() 基础语法
用法示例:
1
2
3
4
5from dataclasses import dataclass, field
class ClassName:
name = field(...) # 字段名: 类型 = Field(参数1=值1, 参数2=值2, ...)field()核心参数说明default- 字段默认值(仅当字段无默认值时使用,与
default_factory二选一) - 示例:
field(default=0)
- 字段默认值(仅当字段无默认值时使用,与
default_factory- 动态生成默认值的工厂函数(如列表/字典等可变类型)
- 示例:
field(default_factory=list)
init- 是否参与
__init__方法(默认 True) - 示例:
field(init=False)
- 是否参与
repr- 是否出现在
__repr__输出中(默认 True)
- 是否出现在
compare- 是否参与比较(
__eq__/__lt__等,默认 True)
- 是否参与比较(
hash- 是否参与
__hash__计算(默认 None,继承compare值)
- 是否参与
metadata- 附加元数据(字典,供外部工具使用)
field(metadata={"desc": "用户ID"})
dataclasses.field() 常用示例
示例:基础使用(默认值/工厂函数)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17from dataclasses import dataclass, field
class User:
# 简单默认值(不可变类型)
id: int = field(default=0)
# 可变类型默认值(必须用 default_factory,避免所有实例共享同一对象)
tags: list[str] = field(default_factory=list)
# 字符串默认值
name: str = field(default="未知用户")
# 实例化
u1 = User()
print(u1) # User(id=0, tags=[], name='未知用户')
u1.tags.append("admin")
u2 = User()
print(u2.tags) # [](独立的列表,无共享问题)示例2:定制初始化/序列化行为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Product:
name: str
# 不参与 __init__(手动赋值)
price: float = field(init=False)
# 不显示在 repr 中
stock: int = field(default=0, repr=False)
# 不参与比较
sku: str = field(default="", compare=False)
# 实例化(无需传 price 和 stock/sku)
p = Product("手机")
p.price = 2999.99 # 手动赋值
print(p) # Product(name='手机', price=2999.99)(stock 未显示)
print(p == Product("手机")) # True(sku 不参与比较)示例3:附加元数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Student:
id: int = field(metadata={"desc": "学生学号", "required": True})
score: float = field(default=0.0, metadata={"min": 0, "max": 100})
# 获取元数据
s = Student(1001)
# 方式1:通过 dataclasses.fields 获取
from dataclasses import fields
for f in fields(s):
print(f.name, f.metadata)
# 输出:
# id {'desc': '学生学号', 'required': True}
# score {'min': 0, 'max': 100}
pydantic.Field(第三方库,数据校验)
pydantic是Python主流的数据校验库Field用于定义模型字段的校验规则、默认值、文档等,功能比dataclasses.field更丰富- 使用前先安装:
1
pip install pydantic
pydantic.Field 基础语法
用法说明:
1
2
3
4from pydantic import BaseModel, Field
class ClassName(BaseModel):
name = field(...) # 字段名: 类型 = Field(默认值, 参数1=值1, 参数2=值2, ...)核心参数说明
default/default_factory:- 默认值/动态默认值(同dataclasses)
- 示例:
Field(default=10)/Field(default_factory=list)
alias- 字段别名(序列化/反序列化时可用)
- 示例:
Field(alias="user_id")
gt/ge/lt/le- 数值大于/大于等于/小于/小于等于
- 示例:
Field(gt=0)(值必须>0)
min_length/max_length- 字符串最小/最大长度
- 示例:
Field(min_length=2, max_length=10)
pattern- 字符串正则匹配
- 示例:
Field(pattern=r"^[A-Z]+$")
description- 字段描述(文档生成)
- 示例:
Field(description="用户年龄")
nullable- 是否允许为None(Pydantic v1,v2需用
Optional) - 示例:
Field(nullable=True)
- 是否允许为None(Pydantic v1,v2需用
examples- 示例值(OpenAPI文档)
- 示例:
Field(examples=[18, 20])
pydantic.Field常用示例
示例1:基础校验
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25from pydantic import BaseModel, Field
class User(BaseModel):
name: str = Field(..., min_length=2, max_length=20, description="用户名(2-20字符)")
age: int = Field(..., gt=0, le=120, description="年龄(1-120)")
email: str = Field(None, pattern=r"^[\w-]+@[\w-]+\.[a-z]+$", description="邮箱(可选)")
# 合法实例
u1 = User(name="张三", age=25, email="zhangsan@example.com")
print(u1.model_dump())
# 输出:{'name': '张三', 'age': 25, 'email': 'zhangsan@example.com'}
# 非法实例(触发校验错误)
try:
u2 = User(name="李", age=150, email="invalid-email")
except Exception as e:
print(e)
# 输出:
# 1 validation error for User
# name
# String should have at least 2 characters [type=string_too_short, input_value='李', input_type=str]
# age
# Input should be less than or equal to 120 [type=less_than_or_equal, input_value=150, input_type=int]
# email
# String should match pattern '^[\w-]+@[\w-]+\.[a-z]+$' [type=string_pattern_mismatch, input_value='invalid-email', input_type=str]示例2:别名与默认值
1
2
3
4
5
6
7
8
9
10
11
12class Product(BaseModel):
# 别名:序列化时用 product_id,反序列化时可传 id 或 product_id
id: int = Field(..., alias="product_id")
# 动态默认值(每次实例化生成新列表)
tags: list[str] = Field(default_factory=lambda: ["未分类"])
# 用别名传参
p = Product(product_id=1001)
print(p.id) # 1001
print(p.tags) # ['未分类']
# 序列化(输出别名)
print(p.model_dump(by_alias=True)) # {'product_id': 1001, 'tags': ['未分类']}示例3:结合文档(OpenAPI)
1
2
3
4
5
6
7
8
9
10from pydantic import BaseModel, Field
from pydantic.schema import schema
class Order(BaseModel):
order_id: str = Field(..., pattern=r"^ORD-\d{6}$", description="订单号(格式:ORD-6位数字)")
amount: float = Field(..., gt=0, examples=[99.9, 199.0], description="订单金额(>0)")
# 生成JSON Schema(用于OpenAPI文档)
schema_dict = schema([Order])
print(schema_dict)
三、pydantic.Field 和 dataclasses.field 区别
- dataclasses.field:
- 内置库
- 简单数据存储、无校验需求
- 无校验能力(仅基础类型注解)
- pydantic.Field:
- 第三方接口
- 接口参数校验、数据清洗、API文档
- 强大的数值/字符串/结构校验
使用注意:
- 可变类型默认值 :
- 无论是
dataclasses.field还是pydantic.Field,可变类型(list/dict/set)的默认值必须用default_factory,否则所有实例会共享同一对象 - 错误:
tags: list = [] - 正确:
tags: list = field(default_factory=list)
- 无论是
- Pydantic版本差异 :
- v1 中
nullable=True允许字段为None;v2 需用Optional[类型](如age: Optional[int] = Field(None)) - v2 中
Field的参数更简洁,推荐使用最新版
- v1 中
- dataclasses 不可变字段 :
- 若需不可变数据类,加
@dataclass(frozen=True),此时init=False的字段需在__post_init__中赋值
- 若需不可变数据类,加