如何使用类装饰器对Python属性进行mypy类型检查
类装饰器配合@property时的mypy类型检查问题
我尝试让以下代码通过mypy类型检查,但遇到了问题:
from typing import Any class Decorator: def __init__(self, func) -> None: self.func = func def __call__(self, *args: Any, **kwargs: Any) -> Any: return self.func(*args, **kwargs) class Foo: @property @Decorator def foo(self) -> int: return 42 f = Foo() # reveal_type(f.foo) a: int = f.foo print(a)
运行这段代码能正确输出42,但执行mypy检查时会报错,显示f.foo的类型为Decorator,无法赋值给int类型变量。若将代码修改为a: int = f.foo(),mypy检查通过,但运行时会触发TypeError,提示'int对象不可调用'。如果改用函数装饰器(如下所示),则代码既能正常运行,也不会出现类型检查错误:
def Decorator(f): return f
使用的环境是Python 3.10.6和mypy 0.991,请问如何使用类装饰器实现正确的类型检查?
解决方案
问题核心在于类装饰器未适配@property的描述符协议,且缺少泛型类型注解让mypy无法推断真实返回类型。修改后的代码如下:
from typing import Generic, TypeVar, Any, Callable # 定义泛型变量,捕获被装饰函数的返回类型 T = TypeVar('T') class Decorator(Generic[T]): def __init__(self, func: Callable[..., T]) -> None: self.func = func def __call__(self, *args: Any, **kwargs: Any) -> T: return self.func(*args, **kwargs) # 实现描述符协议的__get__方法,适配@property逻辑 def __get__(self, instance: Any, owner: type[Any] | None = None) -> T: return self.func(instance) class Foo: @property @Decorator def foo(self) -> int: return 42 f = Foo() a: int = f.foo print(a)
关键修改说明:
- 泛型注解:让
Decorator继承Generic[T],用T绑定被装饰函数的返回类型,替代模糊的Any,让mypy能明确识别返回值类型。 - 实现
__get__方法:@property是描述符,要求被装饰的对象也支持描述符协议。添加__get__后,访问f.foo时会自动调用该方法执行原函数并返回结果,同时让mypy正确推断出属性类型为int而非Decorator实例。
修改后代码可正常运行,且mypy类型检查能通过。
内容的提问来源于stack exchange,提问作者gsgx
相关产品推荐
相关产品推荐

