Python——field的用法


整体说明

  • 在 Python 中,field 主要关联两个核心场景:
    • 一是标准库 dataclasses 模块的 field() 函数 ,用于定制数据类字段
    • 二是第三方库如 pydanticField (注意:首字母是大写), 用于数据校验/序列化

dataclasses.field()

  • dataclasses 是 Python 内置的轻量级数据类工具
  • field() 用于精细化定义数据类的字段(替代默认的简单赋值),支持定制默认值、初始化行为、序列化等
    • 注:Python 3.7+ 内置

dataclasses.field() 基础语法

  • 用法示例:

    1
    2
    3
    4
    5
    from dataclasses import dataclass, field

    @dataclass
    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
    17
    from dataclasses import dataclass, field

    @dataclass
    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
    @dataclass
    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
    @dataclass
    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
    4
    from 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)
    • 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
    25
    from 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
    12
    class 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
    10
    from 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 的参数更简洁,推荐使用最新版
  • dataclasses 不可变字段
    • 若需不可变数据类,加 @dataclass(frozen=True),此时 init=False 的字段需在 __post_init__ 中赋值