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

Python3.11中如何为返回类装饰器的函数添加类型注解?

带参数类装饰器的类型注解方案

无参数类装饰器的正确写法

先回顾能正常通过mypy类型检查的无参数类装饰器写法:

from typing import TypeVar, Type, Any

T = TypeVar('T', bound=Type[Any])

def simple_decorator(cls: T) -> T:
    # 自定义装饰逻辑
    return cls

使用示例:

@simple_decorator
class Foo:
    foo: int

此时mypy能正确识别Foo实例的foo属性类型。


问题场景:带参数的装饰器工厂类型注解失效

当装饰器需要接收参数(参数与被装饰类类型无关)时,若错误地将返回类型指定为Decorator[Any],会导致被装饰类的类型检查失效:

from typing import TypeVar, Type, Any, Callable, TypeAlias

T = TypeVar('T', bound=Type[Any])
Decorator: TypeAlias = Callable[[T], T]

def decorator_factory(some_arg: str) -> Decorator[Any]:
    def wrapper(cls: T) -> T:
        # 根据传入的参数修改类的逻辑
        return cls
    return wrapper

# 此时Foo实例的foo属性无法被mypy正确检查
@decorator_factory("demo")
class Foo:
    foo: int

解决方法:保留泛型参数,避免使用Any

核心是让装饰器工厂返回的装饰器保留泛型参数T,而非用Any抹除类型信息,有两种实现方式:

方式1:直接返回泛型Callable

from typing import TypeVar, Type, Any, Callable

T = TypeVar('T', bound=Type[Any])

def decorator_factory(some_arg: str) -> Callable[[T], T]:
    def wrapper(cls: T) -> T:
        # 示例:根据参数给类添加属性
        setattr(cls, "decorator_arg", some_arg)
        return cls
    return wrapper

# 现在mypy能正常检查Foo的类型
@decorator_factory("demo")
class Foo:
    foo: int

# 验证:类型检查正常
foo_instance = Foo()
foo_instance.foo  # 识别为int类型
foo_instance.decorator_arg  # 识别为str类型

方式2:使用泛型类型别名

如果需要复用Decorator类型,可将其定义为泛型类型别名:

from typing import TypeVar, Type, Any, Callable, TypeAlias

T = TypeVar('T', bound=Type[Any])
# 定义泛型类型别名
Decorator: TypeAlias = Callable[[T], T]

def decorator_factory(some_arg: str) -> Decorator[T]:
    def wrapper(cls: T) -> T:
        return cls
    return wrapper

这种写法同样能让mypy正确跟踪被装饰类的具体类型。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 08:02:42