Python mypy注释装饰器__call__

时间:2020-10-22 15:52:38

标签: python mypy python-typing

我正在尝试注释作为类实现的装饰器,但是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转换为函数,但实际上,它被子类化以具有更多专用选项。

1 个答案:

答案 0 :(得分:0)

您需要将my_decorator设为generic class,并执行以下操作:

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类。这样,当我们在分析__call__的任何调用时尝试使用它时,可以确保绑定到TypeVar的值是“可用的”。

不幸的是,无法确保__call__的参数将与func()的参数匹配。因此,如果您尝试执行类似func(1, 2, 3)的操作,mypy将不会报告错误。

一旦mypy添加了对PEP 612的支持,从而为键入与装饰器相关的代码提供了更好的支持,这可能成为可能。