【问题标题】:Python mypy Annotation Decorators __call__Python mypy 注释装饰器 __call__
【发布时间】:2023-03-23 14:19:01
【问题描述】:

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

【问题讨论】:

    标签: python mypy python-typing


    【解决方案1】:

    您需要将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 的支持,这可能成为可能,这通常会更好地支持键入与装饰器相关的代码。

    【讨论】:

      猜你喜欢
      • 2019-11-13
      • 2013-10-30
      • 1970-01-01
      • 2015-01-03
      • 1970-01-01
      • 2021-11-20
      • 2022-09-21
      • 2021-05-09
      • 2021-10-22
      相关资源
      最近更新 更多