Python:同时用于多个参数的 TypeVar

问题描述 投票:0回答:2

有没有办法让

TypeVar
(或其他格式)捕获函数的所有参数?例如,假设我想包装一个通用函数,使其所有参数都在一个元组中给出:

def invoke(f: Callable[..., T], args: Tuple[...]) -> T:
    return f(*args)

只是,我将使用静态类型检查来强制

...
的内容与函数参数具有相同的类型,而不是省略号 (
Tuple
)。

谢谢。

python python-3.x type-hinting
2个回答
2
投票

您可以修改以下内容以满足您的要求,您可能需要添加额外的处理。

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
的语法糖。


0
投票

答案是,只是不是

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

© www.soinside.com 2019 - 2024. All rights reserved.