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

二阶装饰器的Mypy类型标注错误排查与修正咨询

二阶装饰器类型标注问题

我尝试实现一个二阶装饰器,将动态变量作为被装饰函数的首个参数注入,现有代码如下:

from typing import Callable, Concatenate, ParamSpec, TypeVar

T = TypeVar('T')
U = TypeVar('U')
P = ParamSpec('P')


def foo(some_arg: U) -> Callable[
    [Callable[Concatenate[U, P], T]],
    Callable[P, T],
]:
    def decorator(fn: Callable[Concatenate[U, P], T]) -> Callable[P, T]:
        def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
            return fn(some_arg, *args, **kwargs)

        return wrapper

    return decorator

运行mypy时出现如下错误:

error: Incompatible return value type (
    got "Callable[[Arg(Callable[[U, **P], T], 'fn')], Callable[P, T]]",
    expected "Callable[[Callable[[U, **P], T]], Callable[P, T]]")  [return-value]

我搞不懂错误原因,也找不到Arg相关的文档,想请教:

  • 如何正确声明装饰器工厂的返回值?
  • 怎么解读这个mypy错误?
  • 有没有遗漏的官方文档内容?

错误解读

这个错误里的Arg(...)是mypy内部用来标记带参数名的类型结构的语法,不属于标准Python类型体系。错误的核心原因是:你在foo函数的返回类型注解中,使用了未绑定的泛型变量P和T——这两个泛型变量的作用域应该绑定到内部的decorator函数,而非外层的foo。mypy因此认为返回的decorator函数类型,和你声明的返回类型不匹配。

修复方案

要正确标注,需要将泛型参数P和T的绑定移到decorator函数上(Python 3.12+支持函数级泛型),或者直接将泛型参数声明在foo函数上。

方案1:函数级泛型(Python 3.12+)

from typing import Callable, Concatenate, ParamSpec, TypeVar

T = TypeVar('T')
U = TypeVar('U')
P = ParamSpec('P')


def foo(some_arg: U) -> Callable[[Callable[Concatenate[U, P], T]], Callable[P, T]]:
    def decorator[P, T](fn: Callable[Concatenate[U, P], T]) -> Callable[P, T]:
        def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
            return fn(some_arg, *args, **kwargs)

        return wrapper

    return decorator

方案2:外层函数声明泛型

from typing import Callable, Concatenate, ParamSpec, TypeVar

T = TypeVar('T')
U = TypeVar('U')
P = ParamSpec('P')


def foo[P, T, U](some_arg: U) -> Callable[[Callable[Concatenate[U, P], T]], Callable[P, T]]:
    def decorator(fn: Callable[Concatenate[U, P], T]) -> Callable[P, T]:
        def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
            return fn(some_arg, *args, **kwargs)

        return wrapper

    return decorator

两种写法都能让泛型变量P、T与被装饰的函数正确绑定,解决类型不匹配的问题。

关于Arg的说明

Arg是mypy内部用于追踪参数名称和类型对应关系的结构,不会出现在标准Python类型提示中。它只是mypy在报错时,更详细地展示了参数的名称信息,你不需要在代码中使用它。

文档参考

mypy官方文档中,泛型函数和装饰器类型标注的章节,对Concatenate与ParamSpec的结合使用有详细说明,可重点关注这部分内容。

内容的提问来源于stack exchange,提问作者Nicolas Appriou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 18:39:58