【问题标题】:Constructor and Pydantic构造函数和 Pydantic
【发布时间】:2021-06-30 02:58:22
【问题描述】:

我想创建一个带有构造函数的 Pydantic 类,该构造函数对输入进行一些数学运算并相应地设置对象变量:

class PleaseCoorperate(BaseModel):
    self0: str
    next0: str

    def __init__(self, page: int, total: int, size: int):
        # Do some math here and later set the values
        self.self0 = ""
        self.next0 = ""
    

但是当我尝试实际使用该类 page = PleaseCoorperate(0, 1, 50) 时,我得到了这个错误:

main_test.py:16: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
main.py:46: in __init__
    self.self0 = ""
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   AttributeError: __fields_set__

这里发生了什么?我不能在 Pydantic 类上使用构造函数吗?

【问题讨论】:

    标签: python pydantic


    【解决方案1】:

    您可以使用 pydantic 验证器。这些是您解决方案的完美候选者。

    from pydantic import BaseModel, validator
    
    class PleaseCoorperate(BaseModel):
        self0: str
        next0: str
    
        @validator('self0')
        def self0_math_test(cls, v):  # v set the values passed for self0
            # your math here
            return new_self0
    
        @validator('next0', always=True)  # always if you want to run it even when next0 is not passed (optional)
        def next0_must_have(cls, v, values, **kwargs):  # values sets other variable values
            # your math here
            return new_next0
    

    验证器文档:here

    【讨论】:

    • 谢谢帕克斯。这是一个惊喜。基本上 Pydantic 对象是数据持有者......顺便说一下,我不需要验证输入。我需要根据输入计算对象的字段。
    • 他们有一个例子:@validator('cube_numbers', 'square_numbers') def check_sum(cls, v): if sum(v) > 42: raise ValueError('sum of numbers greater than 42') return v 我不明白。 v 是cube_numbers 还是square_numbers
    • 在这种情况下,这个验证器会一个接一个地验证cubessquares。所以,v 是他们两个。
    【解决方案2】:

    您没有调用 BaseModel 构造函数,因此,您跳过了所有将类变量转换为属性的 pydantic 魔法。这个:

    class PleaseCoorperate(BaseModel):
        self0: str
        next0: str
    
        def __init__(self, page: int, total: int, size: int):
            # Do some math here and later set the values
            self0 = ""
            next0 = ""
            super().__init__(self0=self0, next0=next0)
    

    应该可以解决问题。但是,我可以建议一个更好的选择,它不会用类方法覆盖 pydantic 非常优秀的默认构造函数:

    class PleaseCoorperate(BaseModel):
        self0: str
        next0: str
    
        @classmethod
        def custom_init(cls, page: int, total: int, size: int):
            # Do some math here and later set the values
            self0 = ""
            next0 = ""
            return cls(self0=self0, next0=next0)
    
    x = PleaseCoorperate.custom_init(10, 10, 10)
    

    【讨论】:

      猜你喜欢
      • 2013-10-13
      • 2017-01-21
      • 1970-01-01
      • 1970-01-01
      • 2013-07-07
      • 1970-01-01
      • 2011-03-01
      • 2016-03-24
      • 1970-01-01
      相关资源
      最近更新 更多