如果我有一个"工厂"方法,用一个类的类型和相关的参数来创建一个资源,有没有办法对参数进行静态分析?

from typing import Type

from pydantic import BaseModel

class Res(BaseModel):
    f: int
    class Config:
        extra = "forbid"


def factory[T](resource_type: Type[T], **kwargs) -> T:
    return resource_type(**kwargs)


factory(Res, f=3) # no problem!
factory(Res, f=3, g=4) # ValidationError, g is not allowed.

这在运行时按预期工作.我希望pyright静态地注意到,对于Res,g不是一个有效的参数.

这有可能吗?我正朝ParamSpecs的方向看,但它还没有帮助.

def factory[T, **P](resource_type: Type[T], *args: P.args, **kwargs: P.kwargs) -> T:
    return resource_type(**kwargs)
factory(Res, f=3) # says: Param spec "P@factory" has no bound value

推荐答案

typing.ParamSpec应该是个不错的 Select .错误消息说明了一切:参数规范没有绑定到任何可调用的对象.将签名从type[T]更改为Callable[P, T].

from typing import Callable, ParamSpec, TypeVar, reveal_type

from pydantic import BaseModel

T = TypeVar("T", bound=BaseModel)
P = ParamSpec("P")


class Res(BaseModel):
    f: int

    class Config:
        extra = "forbid"


def factory(resource_type: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T:
    return resource_type(*args, **kwargs)


reveal_type(factory(Res, f=3))  # Revealed type is "Res"

Python-3.x相关问答推荐

Django 5.0.2和django_rest_framework

类型的可变性对变量的作用域有影响吗?

将Trio与基于线程的事件侦听器混合使用

这是重命名极地df列的最好方式吗?

使用数据库将文件从Sharepoint下载到文件系统

合并两个数据帧并对某些总和进行求和

Python-Django 设置 Pandas DataFrame 的多索引不会分组/合并最后一个索引

以特定方式重新排列 pandas 数据框的列

Python根据条件从多行读取值

从一列字符串中提取子字符串并将它们放入列表中

如何根据索引子列表对元素列表进行分组或批处理?

如何通过从特定列创建分组多标题来reshape 数据框?

如果值超出上下限(异常值处理),则将值的数据框替换为 np.nan

无法使用 Python 和 Selenium 检索 href 属性

错误:预期语句,发现 py:Dedent

UnicodeDecodeError:utf-8编解码器无法解码位置 1 的字节 0x8b:无效的起始字节,同时读取Pandas中的 csv 文件

如何通过命令行将数组传递给python

PIL 在图像上绘制半透明方形覆盖

是否在未完成初始化的对象上调用了 del?

如何从 seaborn / matplotlib 图中删除或隐藏 x 轴标签