python3 输入:从 Callable 中提取参数列表

python3 typing: extract argument list from Callable

考虑一个包装另一个函数并将输出放入单例列表的函数:

def listify(func):
    return lambda *kargs, **kwargs: [func(*kargs, **kwargs)]

您将如何在 python3 中输入此函数的类型提示?这是我最好的尝试:

from typing import Callable, TypeVar
T = TypeVar('T')

def listify(func: Callable[..., T]) -> Callable[..., List[T]]:
    return lambda *kargs, **kwargs: [func(*kargs, **kwargs)]

但我不高兴返回的 Callable 没有继承输入 Callable 的参数类型的签名。有没有办法在不对 func?

的参数数量做出假设的情况下实现这一目标

随着 Python 3.10 的发布,对于旧的 Python 版本,typing-extensions package version 3.10.0 and up, you can use a ParamSpec() construct.

ParamSpec() 对象的行为与 TypeVar() object 类似,但它不是充当单个参数的占位符,而是模拟可调用对象接受的参数组合。

在这里使用这样一个对象作为参数的占位符:

from typing import Callable, List, TypeVar
try:
    from typing import ParamSpec
except ImportError:
    from typing_extensions import ParamSpec

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

def listify(func: Callable[P, T]) -> Callable[P, List[T]]:
    return lambda *kargs, **kwargs: [func(*kargs, **kwargs)]

如果您受困于 Python 3.4 或更早版本,那么您将无法使用类型提示执行您想要的操作,因为 type_extensions 3.10.0 不支持 Python 版本,并且没有其他语法可以捕获 TypeVar 泛型中的参数部分。 Callable 最初保持简单是因为它实际上只是表示回调函数。

PEP 612ParamSpec 添加到 python-3.10,这允许:

from typing import Callable, ParamSpec, TypeVar
P = ParamSpec('P')
T = TypeVar('T')

def listify(func: Callable[P, T]) -> Callable[P, List[T]]:
    return lambda *kargs, **kwargs: [func(*kargs, **kwargs)]