You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pyright如何通过partial保留参数类型信息?

关于Pyright对functools.partial的类型推断问题

来看这个简单示例:

from functools import partial

def foo(a: str, b: int, c: float, d: str) -> bool:
    print(a, b, c, d)
    return True

bar = partial(foo, 'a', 1, 2.0)
bar()  # error

Pyright可以正确识别bar还需要一个类型为str的参数d,但它是如何实现的?我查看了Python 3.8-3.10中partial的实际定义以及typeshed中的类型定义。实际定义当然没有类型标注,但typeshed中partial的定义如下:

class partial(Generic[_T]):
    @property
    def func(self) -> Callable[..., _T]: ...
    @property
    def args(self) -> tuple[Any, ...]: ...
    @property
    def keywords(self) -> dict[str, Any]: ...
    def __new__(cls, __func: Callable[..., _T], *args: Any, **kwargs: Any) -> Self: ...
    def __call__(__self, *args: Any, **kwargs: Any) -> _T: ...
    if sys.version_info >= (3, 9):
        def __class_getitem__(cls, item: Any) -> GenericAlias: ...

该定义中没有任何保留类型信息的逻辑,因为它仅用Any和...来表示参数。你甚至可以复制该定义并将其重命名为mypartial,使用后会发现无法获得相同的类型安全性。我了解可以通过ParamSpec保留类型信息,但此处并未使用,且我的Python版本也无法访问它。

是我遗漏了什么内容,还是Pyright直接硬编码了相关规则,不受类型定义的限制?


答案是Pyright确实对functools.partial做了特殊的硬编码处理,并没有完全依赖typeshed中的类型定义。

类型检查器为了支持这类常见的标准库工具,会针对部分内置/标准库函数添加专门的类型推断逻辑,而非仅依赖表面的类型标注。对于partial,Pyright会在分析代码时,追踪原函数的签名,结合传入的固定参数和关键字参数,动态计算出返回的可调用对象的剩余参数类型。

typeshed里的定义是兼容性的“兜底”版本,用Any和Callable[..., _T]保证在不支持复杂类型推断的检查器中也能正常工作,但Pyright这类进阶工具会绕过这个通用定义,直接实现针对partial的精确类型推导。

你复制定义成mypartial后无法获得同样效果,就是因为Pyright没有为这个自定义类添加特殊处理逻辑,只能按照普通泛型类解析,自然无法保留原函数的参数信息。

内容的提问来源于stack exchange,提问作者Anthony Naddeo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 00:12:17