pydantic:无字段的默认值

问题描述 投票:0回答:1

根据 官方 Pydantic 指南

None
的值是具有默认值的可选字段的有效值。 如何更改它以使
None
值被默认值替换? 我的用例是 Pandas 数据框中的一条记录,因此某些字段可以是
None
:

from pydantic import BaseModel, field_validator
from typing import Optional, Union
import pandas as pd
import json

class Person(BaseModel):
    name: str
    age: Optional[int] = 10

    @field_validator("age", mode="before")
    @classmethod
    def lower_age(cls, value: int) -> Union[int, None]:
        return None if value is None or pd.isna(value) else value - 1
    
if __name__ == "__main__":
    df_person = pd.DataFrame({
        "name": ["Alice", "Bob"],
        "age": [10, None]
    })

    person_list = df_person.to_dict(orient="records")
    for p in person_list:
        m = Person.model_validate(p)
        print(json.dumps(m.model_dump(), indent=4))

在这个 MWE 中,我希望 Bob 得到的值为 10,而不是 null。 我知道我可以更改 field_validator 以使其返回默认值,但这意味着我必须输入 def

python pydantic
1个回答
0
投票

如果您没有使用 Pydantic,我会推荐以下结构。默认值是

__init__
的属性,而不是属性本身。

class Person:
    name: str
    age: int

    def __init__(self, name: str, age: int = 10):
        self.name = name
        self.age = 10

如果您想使用像

None
这样的哨兵“明确”设置默认年龄,我会将
 __init__
更改为

def __init__(self, name: str, age: Optional[int] = None):
    self.name = name
    if age is not None:
        self.age = age
    else:
        self.age = 10

Pydantic 引入的问题是,它将 attribute 的类型与 __init__ 用于初始化属性的

parameter
的类型混为一谈。我首先要说的是,我对 Pydantic 不太熟悉,不知道什么是好的解决方法,但对于标准库
dataclasses
,我主张定义一个单独的 init var 来初始化该字段。例如,

@dataclass
class Person:
    name: str
    age: int = field(default=10, init=false)

    age_: InitVar[Optional[int]] = None

    def __post_init__(self, age_):
        if age_ is not None:
            self.age = age_
        else:
            self.age = fields(Person)[1].default

代码更多,但是

  1. 准确输入
    age
    属性
  2. 区分提供 no 值来初始化
    age
    和提供哨兵来触发默认值分配。

(类似,如果不是几乎相同,Pydantic 的代码应该是可能的。)

© www.soinside.com 2019 - 2024. All rights reserved.