我有一个包含所有必要参数的类。但是,对于 init 函数,它要求关键字参数,并且不接受位置参数。所以,我的问题是:我可以在 pydantic.BaseModel 的配置中更改一些内容以允许位置参数吗?
这是我的班级的一个例子:
class Foo(BaseModel):
a: int
b: Optional[str]
c: Optional[float]
所以,我无法像这样初始化类:
Foo(1,2,2.5)
# instead, I should init it like this:
Foo(a=1,b=2,c=2.5)
所以,我需要能够将位置关键字传递给类。可以吗?
在 pycharm 中使用的带有类型提示的覆盖
__init__
方法示例
class Foo(BaseModel):
a: int
b: Optional[str]
c: Optional[float]
def __init__(self, a: int,
b: Optional[str] = None,
c: Optional[float] = None,
**kwargs) -> None:
super(Foo, self).__init__(a=a, b=b, c=c, **kwargs)
Pydantic 对象不支持位置参数,除非你按照 Arseniy Lebedev 的建议自己实现它。
这是为什么呢? 以下是一些原因:
import json
from pydantic import BaseModel
from typing import Optional
class Foo(BaseModel):
a: int
b: Optional[str]
c: Optional[float]
您可以为 Pydantic 提供您想要用来初始化模型的每个密钥(您所做的):
Foo(a=1,b="2",c=2.5)
或者你可以使用 json:
json_raw = '{"a": 1, "b": "2", "c": 3}'
some_dict = json.loads(json_raw)
my_foo = Foo(**some_dict)
或两者的混合:
json_raw = '{"a": 1, "b": "2"}'
some_dict = json.loads(json_raw)
my_foo = Foo(**some_dict, c=3)
请勿使用此代码:
def model_from_args(model, args):
return model(**{field: arg for field, arg in zip(model.model_fields, args)})
更改模型后,破坏代码的可能性非常高。
您可以使用创建带有位置参数的对象的类方法来扩展
BaseModel
类。 cls.__annotations__
返回你的 pydantic 字段的字典(按照你声明它们的顺序)。使用 *args
,您可以通过使用可用于实例化对象的位置参数压缩字段来创建字典。
from pydantic import BaseModel
class MasterObj(BaseModel):
@classmethod
def create_from_list(cls, *args):
annotations = cls.__annotations__
zipped = dict(zip(annotations, args))
return cls(**zipped)
class Specs(MasterObj):
spec_type: str
hp: int = 0
attack: int = 0
spattack: int = 0
defence: int = 0
spdefence: int = 0
speed: int = 0
if __name__ == '__main__':
s = Specs.create_from_list('main', 100, 100, 100, 100, 100, 100)
您还可以实现一些错误处理来捕获是否提供了过多或过少的位置参数等。