如何输入像 pydantic 和 dataclass 这样的动态类实例化?

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

Pydantic 和 Dataclass 都可以根据属性及其类型来提示对象创建,如以下示例所示:

from pydantic import BaseModel, PrivateAttr, Field
from dataclasses import dataclass

# Pydantic way
class Person(BaseModel):

    name : str
    address : str
    _valid : bool = PrivateAttr(default=False)


#dataclass way
@dataclass
class PersonDataclass():

    name : str
    address : str
    _valid : bool = False

bob = Person(name="Bob", address="New York")

bobDataclass = PersonDataclass("Bob", "New York")

使用此代码,我可以获得有关对象创建的类型提示(请参见下面的屏幕截图):

pydantic typehint on object creation

dataclass typehint on object creation

不仅如此,对象的属性也被记录下来。


我研究了pydantic的代码,试图达到同样的结果,但我做不到。我尝试的代码是这样的:

class MyBaseModelMeta(type):

    def __new__(cls, name, bases, dct):

        def new_init(self : cls, /, name : str, address : str):
            self.name = name
            self.address = address
            self._valid = False

        dct["__init__"] = new_init
        dct["__annotations__"] = {"__init__": {"name": str, "address": str, "_valid": bool}}
        return super().__new__(cls, name, bases, dct)


class MyBaseModel(metaclass=MyBaseModelMeta):
    
    def __repr__(self) -> str:
        return f"MyBaseModel: {self.__dict__}"


class MyPerson(MyBaseModel):
    pass

myBob = MyPerson("Bob", "New York")

我的类有效(动态 init 插入有效),但类和对象没有得到类型提示。

my class works but it doesn't get typehinted

我做错了什么?我怎样才能实现类型提示?

python python-typing pydantic python-dataclasses
2个回答
7
投票

@chepner 是对的。

静态类型检查器不会执行您的代码,它们只是读取它。

回答你的问题 Pydantic 和

dataclasses
是如何做到的 - 他们作弊:

特殊插件允许

mypy
推断实际上仅在运行时创建的签名。 (当然,我只是开玩笑说“作弊”,但你明白我的意思。)

如果您希望静态类型检查器考虑您自己的动态注释,您将 have 为它们编写自己的插件。


5
投票

@Daniil Fajnberg 大部分是正确的,

但根据您的类型检查器,您可以使用

dataclass_transform
(Python 3.11)

__dataclass_transform__
早期采用者计划装饰器。

Pylance 和 Pyright(通常在 VS-Code 中使用)至少可以使用这些。

尽管如此,您只能模仿数据类的行为,但我认为您无法定义您的元类添加额外的字段。 :/

编辑: 至少 pydantic 将这个装饰器用于他们的 BaseModel:https://pydantic-docs.helpmanual.io/visual_studio_code/#technical-details

如果你仔细研究 pydantic 的代码,你会发现他们的 ModelMetaclass 是用

__dataclass_transform__

装饰的
© www.soinside.com 2019 - 2024. All rights reserved.