有没有办法让
TypeVar
(或其他格式)捕获函数的所有参数?例如,假设我想包装一个通用函数,使其所有参数都在一个元组中给出:
def invoke(f: Callable[..., T], args: Tuple[...]) -> T:
return f(*args)
只是,我将使用静态类型检查来强制
...
的内容与函数参数具有相同的类型,而不是省略号 (Tuple
)。
谢谢。
您可以修改以下内容以满足您的要求,您可能需要添加额外的处理。
from typing import Any
class TypeEnforce:
def __init__(self, func):
self.func = func
def __call__(self, *args):
types = dict(zip(self.func.__annotations__.values(), args))
for k, v in types.items():
if k is Any:
continue
assert type(v) == k
self.func(*args)
示例
@TypeEnforce
def my_test(x: str, y: int) -> None:
print(f"'x' is a {type(x).__name__}")
@TypeEnforce
def my_other_test(x: Any):
return x
my_test("Test", "eight")
my_other_test("Test2")
将导致
AssertionError
,因为函数 my_test
接受 (str
, int
) 但传递了 (str
, str
)。还有一些边缘情况,其中 TypedDict
的提示总是会失败,因为它不是真正的类型,而是 dict
的语法糖。
答案是是,只是不是
TypeVar
。应该使用 ParamSpec
[1]:
from typing import ParamSpec, TypeVar, Callable
P = ParamSpec('P')
RT = TypeVar('RT')
def invoke(f: Callable[P, RT], args: P.args) -> RT:
return f(*args)
# Or, makes more sense:
def invoke(f: Callable[P, RT], args: P.args, **kwargs: P.kwargs) -> RT:
return f(*args, **kwargs)
请注意,对于 python 来说是 < 3.10, one should import it from
typing_extensions
而不是 typing
。
[1] https://docs.python.org/3/library/typing.html#typing.ParamSpec