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
相关产品推荐
相关产品推荐

