【发布时间】:2018-04-14 01:58:06
【问题描述】:
考虑以下代码:
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) 我想在参数中注入用户名。因此,我修改了函数签名。
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
我无法找到正确的输入方式。我知道在这个例子中,装饰函数和返回函数在技术上应该具有相同的签名(但即使这样也没有被检测到)。
【问题讨论】:
-
可调用参数真的很难输入;各种提案四处流传,但目前,我唯一能告诉你的是继续使用
...。 -
我也是这么想的。我没有找到任何东西,除了在 GitHub 上打开的一些问题,建议添加诸如
StarArg和StarKwarg之类的类型。我想知道在这种非常特殊的情况下是否有解决方案,但我认为不会有任何解决方案:( -
您发现类型提示开发人员正在进行讨论以改善这种情况。
标签: python python-3.x decorator type-hinting python-typing