gpt4 book ai didi

装饰器的 Python 3 类型提示

转载 作者:太空狗 更新时间:2023-10-29 16:56:57 25 4
gpt4 key购买 nike

考虑以下代码:

from typing import Callable, Any

TFunc = Callable[..., Any]

def get_authenticated_user(): return "John"

def require_auth() -> Callable[TFunc, TFunc]:
def decorator(func: TFunc) -> TFunc:
def wrapper(*args, **kwargs) -> Any:
user = get_authenticated_user()
if user is None:
raise Exception("Don't!")
return func(*args, **kwargs)
return wrapper
return decorator

@require_auth()
def foo(a: int) -> bool:
return bool(a % 2)

foo(2) # Type check OK
foo("no!") # Type check failing as intended

这段代码按预期工作。现在假设我想扩展它,而不是仅仅执行 func(*args, **kwargs) 我想在参数中注入(inject)用户名。因此,我修改了函数签名。

from typing import Callable, Any

TFunc = Callable[..., Any]

def get_authenticated_user(): return "John"

def inject_user() -> Callable[TFunc, TFunc]:
def decorator(func: TFunc) -> TFunc:
def wrapper(*args, **kwargs) -> Any:
user = get_authenticated_user()
if user is None:
raise Exception("Don't!")
return func(*args, user, **kwargs) # <- call signature modified

return wrapper

return decorator


@inject_user()
def foo(a: int, username: str) -> bool:
print(username)
return bool(a % 2)


foo(2) # Type check OK
foo("no!") # Type check OK <---- UNEXPECTED

我想不出正确的输入方式。我知道在这个例子中,装饰函数和返回函数在技术上应该具有相同的签名(但即使这样也没有被检测到)。

最佳答案

您不能使用 Callable 来说明任何关于附加参数的信息;它们不是通用的。您唯一的选择是说您的装饰器接受一个 Callable 并返回一个不同的 Callable

在您的情况下,您可以使用 typevar 确定返回类型:

RT = TypeVar('RT')  # return type

def inject_user() -> Callable[[Callable[..., RT]], Callable[..., RT]]:
def decorator(func: Callable[..., RT]) -> Callable[..., RT]:
def wrapper(*args, **kwargs) -> RT:
# ...

即使这样,当您使用 reveal_type()

目前正在讨论使 Callable 更灵活的各种提议,但这些提议尚未实现。见

一些例子。该列表中的最后一个是包含您的特定用例的伞票,即更改可调用签名的装饰器:

Mess with the return type or with arguments

For an arbitrary function you can't do this at all yet -- there isn't even a syntax. Here's me making up some syntax for it.

关于装饰器的 Python 3 类型提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47060133/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com