装饰器的类型注释

时间:2021-02-28 11:39:30

标签: python

这不是一个大问题,但我只是想知道解决这个问题的方法。 由于我是在 Python 上使用函数注释的新手,所以我对它并不熟悉。我在下面有一个问题。

当你制作一个装饰器并想在上面加注解时,你会怎么做?

例如,如下代码。

def decorator(func: Callable[[*args,**kwargs], <what type should be here?>]) -> <??>:
    def new_func(*args, **kwargs):
        return func(*args, **kwargs)
    return new_func

1 个答案:

答案 0 :(得分:0)

使用 Any 作为返回类型并返回另一个返回类型为 CallableAny。从 PEP 484python standard library 中,Callable 的第一个参数必须是可调用参数的类型,而不是参数本身。因此,您在 *args 中使用 **kwargsCallable 是不被接受的。相反,您必须使用省略号 ...(允许任意数量的位置和关键字参数类型)。

使用泛型类型 (typing.TypeVar) 更清晰地表达装饰器函数。通俗地说,泛型就是允许类型作为参数的东西。

mypy docs 转述(仅供参考mypypython 的静态类型检查器包):

<块引用>

装饰器函数可以使用泛型类型来表达。泛型可以 被限制为使用特定类型的子类型的值 关键字参数 bound=...。一个上限可用于 保留装饰器装饰的包装函数的签名。

因此,您的示例变为:

from typing import Any, Callable, TypeVar, cast

F = TypeVar('F', bound=Callable[..., Any])

def decorator(func: F) -> F:
    def new_func(*args, **kwargs):
        return func(*args, **kwargs)
    return cast(F, new_func)

同样从 mypy docsPEP 484 中转述:

<块引用>

使用 F 上的绑定,以便在 非功能将被拒绝。此外,包装函数 (new_func) 未进行类型检查,因为(当前)不支持 使用可变数量的参数指定回调签名 一个特定的类型,所以我们必须在最后转换类型。

相关问题