【问题标题】:How to annotate the type of a decorator of an async function in Python 3.7?如何在 Python 3.7 中注释异步函数的装饰器类型?
【发布时间】:2020-09-16 00:38:48
【问题描述】:

我想为异步函数编写一个装饰器。如何注释装饰器定义的类型?

这是我想做的一个例子:

from typing import TypeVar # will Awaitable help?
AsyncFn = TypeVar('AsyncFn') # how to narrow this type definition down to async functions?

def my_decorator(to_decorate: AsyncFn) -> AsyncFn:
    async def decorated(*args, **kwargs): # mypy keeps saying "Function is missing a type"
       return await to_decorate(*args, **kwargs)

@my_decorator
async def foo(bar: int) -> str:
    return f"async: {bar}"

@my_decorator
async def quux(spam: str, **eggs: str) -> None:
    return

foo(1) # should check
foo("baz") # mypy should yell
quux("spam") # should check
quux(1) # mypy should complain
quux(spam="lovely", eggs="plentiful") # ok
quux(spam=1, eggs=0) # mypy should throw a fit

【问题讨论】:

  • 我从未尝试过,但我相信Coroutine 是合适的。
  • 看起来不错;当我reveal_type(my_async_fn) 我得到类似def (bar: builtins.str) -> typing.Coroutine[Any, Any, builtins.int] 的东西。
  • 仔细阅读mypy.readthedocs.io/en/stable/… 表明内部函数可以作为任何类型输入,只要它转换为输入函数的类型即可。

标签: python python-3.x python-asyncio mypy


【解决方案1】:

async 函数是返回 Awaitable 的函数。

在 Python 3.10 中引入了ParamSpecasync 函数的装饰器的完整类型注释是:

from typing import Awaitable, Callable, ParamSpec, TypeVar

T = TypeVar("T")
P = ParamSpec("P")


def decorator(fn: Callable[P, Awaitable[T]]) -> Callable[P, Awaitable[T]]:
    async def decorated(*args: P.args, **kwargs: P.kwargs) -> T:
        return await fn(*args, **kwargs)

    return decorated

在 Python 3.7 中,ParamSpec 可以从 typing_extensions 导入。

【讨论】:

    猜你喜欢
    • 2022-09-21
    • 2021-12-29
    • 1970-01-01
    • 2023-03-17
    • 2021-11-30
    • 2013-02-10
    • 1970-01-01
    • 2023-03-23
    • 2019-11-13
    相关资源
    最近更新 更多