如何注释转发给另一个函数的参数类型?
How to annotate the type of arguments forwarded to another function?
假设我们有一个调用 open()
但带有固定参数的普通函数:
def open_for_writing(*args, **kwargs):
kwargs['mode'] = 'w'
return open(*args, **kwargs)
如果我现在尝试调用 open_for_writing(some_fake_arg = 123)
,没有类型检查器(例如 mypy)可以判断这是一个错误的调用:它缺少必需的 file
参数,并且正在添加另一个参数不是 open
签名的一部分。
如何告诉类型检查器 *args
和 **kwargs
必须是 open
参数规范的子集?我意识到 Python 3.10 有新的 ParamSpec
类型,但它似乎不适用于这里,因为您无法获得像 open
这样的具体函数的 ParamSpec
。
我认为开箱即用这是不可能的。但是,您可以编写一个装饰器,它将包含您要检查的参数(在您的情况下打开)作为输入的函数和 returns 装饰函数,即在您的情况下 open_for_writing 。这当然只适用于 python 3.10 或使用 typing_extensions 因为它使用了 ParamSpec
from typing import TypeVar, ParamSpec, Callable, Optional
T = TypeVar('T')
P = ParamSpec('P')
def take_annotation_from(this: Callable[P, Optional[T]]) -> Callable[[Callable], Callable[P, Optional[T]]]:
def decorator(real_function: Callable) -> Callable[P, Optional[T]]:
def new_function(*args: P.args, **kwargs: P.kwargs) -> Optional[T]:
return real_function(*args, **kwargs)
return new_function
return decorator
@take_annotation_from(open)
def open_for_writing(*args, **kwargs):
kwargs['mode'] = 'w'
return open(*args, **kwargs)
open_for_writing(some_fake_arg=123)
open_for_writing(file='')
如图 here 所示,mypy 现在抱怨收到未知参数。
假设我们有一个调用 open()
但带有固定参数的普通函数:
def open_for_writing(*args, **kwargs):
kwargs['mode'] = 'w'
return open(*args, **kwargs)
如果我现在尝试调用 open_for_writing(some_fake_arg = 123)
,没有类型检查器(例如 mypy)可以判断这是一个错误的调用:它缺少必需的 file
参数,并且正在添加另一个参数不是 open
签名的一部分。
如何告诉类型检查器 *args
和 **kwargs
必须是 open
参数规范的子集?我意识到 Python 3.10 有新的 ParamSpec
类型,但它似乎不适用于这里,因为您无法获得像 open
这样的具体函数的 ParamSpec
。
我认为开箱即用这是不可能的。但是,您可以编写一个装饰器,它将包含您要检查的参数(在您的情况下打开)作为输入的函数和 returns 装饰函数,即在您的情况下 open_for_writing 。这当然只适用于 python 3.10 或使用 typing_extensions 因为它使用了 ParamSpec
from typing import TypeVar, ParamSpec, Callable, Optional
T = TypeVar('T')
P = ParamSpec('P')
def take_annotation_from(this: Callable[P, Optional[T]]) -> Callable[[Callable], Callable[P, Optional[T]]]:
def decorator(real_function: Callable) -> Callable[P, Optional[T]]:
def new_function(*args: P.args, **kwargs: P.kwargs) -> Optional[T]:
return real_function(*args, **kwargs)
return new_function
return decorator
@take_annotation_from(open)
def open_for_writing(*args, **kwargs):
kwargs['mode'] = 'w'
return open(*args, **kwargs)
open_for_writing(some_fake_arg=123)
open_for_writing(file='')
如图 here 所示,mypy 现在抱怨收到未知参数。