首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Pydantic -如何对内置类型进行子类划分

Pydantic -如何对内置类型进行子类划分
EN

Stack Overflow用户
提问于 2021-02-07 11:38:17
回答 2查看 1.1K关注 0票数 0

我正在尝试创建一个timedelta的子类,它期望接收毫秒而不是秒,但它目前不起作用。

我是在反对吗?有没有一种“正确”的方法来实现这一点与皮丹蒂克?还是我需要告诉皮丹蒂克,MillisecondTimedelta只是一个timedelta

代码语言:javascript
复制
from datetime import timedelta

from pydantic import BaseModel


class MillisecondTimedelta(timedelta):
    @classmethod
    def __get_validators__(cls):
        # timedelta expects seconds
        yield lambda v: v / 1000
        yield cls


class MyModel(BaseModel):
    td: MillisecondTimedelta

data = {
    "td": 7598040,
}

print(MyModel(**data))

在以下方面的成果:

代码语言:javascript
复制
Traceback (most recent call last):
  File "main.py", line 14, in <module>
    class MyModel(BaseModel):
  File "pydantic/main.py", line 262, in pydantic.main.ModelMetaclass.__new__
  File "pydantic/fields.py", line 315, in pydantic.fields.ModelField.infer
  File "pydantic/fields.py", line 284, in pydantic.fields.ModelField.__init__
  File "pydantic/fields.py", line 362, in pydantic.fields.ModelField.prepare
  File "pydantic/fields.py", line 541, in pydantic.fields.ModelField.populate_validators
  File "pydantic/class_validators.py", line 255, in pydantic.class_validators.prep_validators
  File "pydantic/class_validators.py", line 238, in pydantic.class_validators.make_generic_validator
  File "/usr/lib/python3.8/inspect.py", line 3105, in signature
    return Signature.from_callable(obj, follow_wrapped=follow_wrapped)
  File "/usr/lib/python3.8/inspect.py", line 2854, in from_callable
    return _signature_from_callable(obj, sigcls=cls,
  File "/usr/lib/python3.8/inspect.py", line 2384, in _signature_from_callable
    raise ValueError(
ValueError: no signature found for builtin type <class '__main__.MillisecondTimedelta'>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-02-07 14:59:04

啊哈,原来我需要改变两件事。

  1. 实际上,从验证器返回一个timedelta,我返回的是cls,这是我的自定义子类。
  2. 不要子类timedelta
代码语言:javascript
复制
from datetime import timedelta

from pydantic import BaseModel


class MillisecondTimedelta:

    @classmethod
    def __get_validators__(cls):
        yield lambda v: timedelta(milliseconds=v)


class MyModel(BaseModel):
    td: MillisecondTimedelta


data = {
    "td": 7598040,
}

print(repr(MyModel(**data)))
代码语言:javascript
复制
MyModel(td=datetime.timedelta(seconds=7598, microseconds=40000))
票数 0
EN

Stack Overflow用户

发布于 2021-02-07 12:09:31

__get_validators__()所示,您需要生成一个或多个验证器。

下面报告了修改后的类;问题是Pydantic理解(对于timedelta字段) int,并以秒(来源)形式浮动。

代码语言:javascript
复制
class MillisecondTimedelta(timedelta):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        if any(isinstance(v, t) for t in (int, float)):
            return cls(milliseconds=v)

现在一切都应该正常工作。

代码语言:javascript
复制
>>> data = {"td": 1000}
>>> print(MyModel(**data))
td=MillisecondTimedelta(seconds=1)

编辑:如果没有自定义类和验证器,就可以使用一个函数来编辑分配给类构造函数的值;它需要修饰这个函数,如图所示

代码语言:javascript
复制
class MyModel(BaseModel):
    td: timedelta

    @validator('td')
    def convert_to_ms(cls, v):
        return v / 1000

此外,这一解决方案也在发挥作用:

代码语言:javascript
复制
>>> data = {"td": 3000}
>>> print(MyModel(**data))
td=datetime.timedelta(seconds=3)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66087455

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档