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

如何使用类装饰器对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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 20:15:44