我有一个工作函数,如下所示:
from time import monotonic
from itertools import chain
from datetime import timedelta
from typing import Callable, Sequence, Any, ParamSpec
P = ParamSpec('P')
def test_function(
func: Callable[P, Any],
args: list[P.args], # Error: "args" member of ParamSpec is valid only when used with *args parameter
kwargs: list[P.kwargs] # Error: "kwargs" member of ParamSpec is valid only when used with **kwargs parameter
) -> None:
for a, kw in zip(args, kwargs):
args_str = ', '.join(chain(
(str(i) for i in a),
(f"{k}={v}" for k, v in kw.items())
))
start = monotonic()
func(*a, **kw)
print(
f"{func.__name__}({args_str}) "
f"executed in: {timedelta(seconds=monotonic() - start)}"
)
此函数的一些基本用法如下所示:
>>> def f1(a: int, b: float, *, c: int):
... return a + b + c
...
>>> test_function(f1, [(1, 2), (3, 4)], [{'c': -1}, {'c': -2}]) # essentially no type hints here for args =(
f1(1, 2, c=-1) executed in: 0:00:00.000006
f1(3, 4, c=-2) executed in: 0:00:00.000004
>>>
它对我来说唯一的问题是它的args
和kwargs
参数的类型提示.正如您所看到的,我试图使用ParamSpec,但是,它给出了一个错误(我在上面的代码注释中指出了这一点),并且在阅读了文档之后,我意识到,不幸的是,我不能随心所欲地使用这种类型:
它们仅在用于串联时有效,或用作Callable的第一个参数,或用作用户定义泛型的参数.
因此,我的问题是:有没有办法仍然验证包含几组参数的序列,每组参数都必须与函数签名匹配?