首页 > 解决方案 > Python mypy 注释装饰器 __call__

问题描述

我正在尝试对作为类实现的装饰器进行注释,但 mypy 似乎要么丢失了注释,要么丢失了类型并认为它是 Any。我要注释的内容:

class my_decorator:
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kwargs):
        return self.func(*args, **kwargs)

@my_decorator
def func():
    return 2

我如何注释这个所以 func 被检测为在装饰后返回一个 int ?我意识到上面看起来很简单,我可以将 my_decorator 转换为一个函数,但实际上它是子类化的,具有更专业的选项。

标签: pythonmypypython-typing

解决方案


您将需要创建my_decorator一个通用类并执行以下操作:

from typing import Any, Callable, Generic, TypeVar

T = TypeVar('T')

class my_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)

@my_decorator
def func() -> int:
    return 2

也就是说,使用 TypeVar 捕获函数的返回类型,该类型的范围仅限于您的my_decorator类。这确保了绑定到 TypeVar 的值在我们分析任何__call__.

不幸的是,无法确保 的参数__call__与 的参数匹配func()。因此,如果您尝试执行类似func(1, 2, 3).

一旦 mypy 添加了对PEP 612的支持,这可能会成为可能,这通常会更好地支持键入与装饰器相关的代码。


推荐阅读