函数参数的类型注释 [duplicate]

Type annotation for the arguments of a function [duplicate]

提问人:Carlos 提问时间:9/18/2023 最后编辑:Carlos 更新时间:9/18/2023 访问量:52

问:

请看下面的例子:

from typing import TypeVar
from collections.abc import Callable

T0 = TypeVar("T0")
T1 = TypeVar("T1")
T2 = TypeVar("T2")

def my_fun(a: str, b: int) -> None:
    print(int(a) + b)
    return None

def fun_caller(f: Callable[[T0, T1], T2], *args: tuple[T0, T1]) -> T2:
    return f(*args)

fun_caller(my_fun, "1", 2)

我想将一个函数后跟该函数的参数传递给另一个函数。 上面的示例起作用,因为类型检查器知道 中使用了正确数量的参数和正确的参数类型。但是,此示例仅适用于具有 2 个输入参数的函数,我想将其推广到任意数量的未知类型的参数。fun_caller(my_fun, "1", 2)

另请注意以下示例:

from typing import TypeVar, Any
from collections.abc import Callable

T = TypeVar("T")

def my_fun(a: str, b: int) -> None:
    print(int(a) + b)
    return None

def fun_caller(f: Callable[..., T], *args: tuple[Any, ...]) -> T:
    return f(*args)

fun_caller(my_fun, 0, 2, "a") # I want the type checker to complain, e.g.,
                              # first arg should be str
                              # there should only be 2 args, not 3

这是行不通的,因为现在类型检查器不会抱怨无效的参数数量和无效的参数类型。此代码将按预期引发,但我想在类型检查器中捕获此问题。TypeError: my_fun() takes 2 positional arguments but 3 were given

python 类型

评论

0赞 Carlos 9/18/2023
@AbdulAzizBarkat不,我的第二个例子中显示了类似的东西,我解释了为什么我想要一些不同的东西
2赞 Abdul Aziz Barkat 9/18/2023
这个问题有多个答案,其中一个建议使用看看那个......ParamSpec
1赞 jkr 9/18/2023
具体请参阅 stackoverflow.com/a/67814270/5666087。看看 PEP 612,它可以与 Python 3.10+ 一起使用。如果您使用的是旧版本的 Python,恐怕这是不可能的。
0赞 Carlos 9/18/2023
@AbdulAzizBarkat你是对的,我错过了第二个答案,它有效。

答:

1赞 Carlos 9/18/2023 #1

刚刚发现这可以通过 ParamSpec 来实现。例:

# pyright: strict

from typing import ParamSpec, TypeVar
from collections.abc import Callable

P = ParamSpec("P")
T = TypeVar("T")

def my_fun1(a: str, b: int) -> None:
    print(int(a) + b)
    return None

def my_fun2(a: str, b: int, c: float) -> None:
    print(int(a) + b*c)
    return None

def fun_caller(f: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T:
    return f(*args, **kwargs)

fun_caller(my_fun1, "1", 2)             # no issues reported
fun_caller(my_fun2, "1", 2, 3.14)       # no issues reported
fun_caller(my_fun2, c=3.14, a="1", b=2) # no issues reported
fun_caller(my_fun1, 0, 2, "a")          # Argument of type "Literal[0]" cannot be assigned to parameter of type "str"
                                        # Expected 2 positional arguments