Python 中可以输入 *(解包)运算符吗?或者任何其他可变参数函数,使得所有可变参数类型都在结果类型中?

2024-02-01

使用类型存根,我想知道是否可以在 Python 中表达一种类型,允许您为任意数量的参数正确键入:

def test(*args):
  return args

乍一看,我带着:

T = TypeVar('T')
def test(*args: T) -> Tuple[T, ...]:
  return args

但这当然只能正确输入第一个 T。

是为所有参数编写覆盖的唯一可能方法吗?

T1 = TypeVar('T1')
T2 = TypeVar('T2')
T3 = TypeVar('T3')
T4 = TypeVar('T4')

@overload
def test(arg1: T1) -> Tuple[T1]: ...
@overload
def test(arg1: T1, arg2: T2) -> Tuple[T1, T2]: ...
@overload
def test(arg1: T1, arg2: T2, arg3: T3) -> Tuple[T1, T2, T3]: ...
@overload
def test(arg1: T1, arg2: T2, arg3: T3, arg4: T4) -> Tuple[T1, T2, T3, T4]: ...
# etc
def test(*args: Any) -> Tuple[Any, ...]:
  return args

这也不完整,因为它没有携带足够的类型信息来键入以下内容:

x: Tuple[int, int, str] = test(*[1, 2, "4"])

这可以通过解决TypeVarTuple from PEP646 https://peps.python.org/pep-0646/,在Python 3.11或前向兼容模块中实现打字扩展 https://pypi.org/project/typing-extensions/.

请参阅这个模拟示例:

from __future__ import annotations

from typing import Any, Callable, Generic
from typing_extensions import TypeVarTuple, Unpack  # typing_extensions only needed for Python < 3.11

Ts = TypeVarTuple("Ts")

class Signal(Generic[Unpack[Ts]]):
    def add_callback(self, func: Callable[[Unpack[Ts]], Any]) -> None:
        ...

    def emit(self, *args: Unpack[Ts]) -> None:
        ...

def callback(a: int, b: str) -> None:
    ...

def callback_bad(a: str) -> None:
    ...

sig: Signal[int, str] = Signal()
sig.add_callback(callback)  # Good lint
sig.add_callback(callback_bad)  # Bad lint

sig.emit(1223, "foo")  # Good lint
sig.emit("bar")  # Bad lint

另请参阅类型序列的动态 TypeVar https://stackoverflow.com/questions/73454375/dynamic-typevar-for-a-sequence-of-types/73493440#73493440寻求解决方案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 中可以输入 *(解包)运算符吗?或者任何其他可变参数函数,使得所有可变参数类型都在结果类型中? 的相关文章

随机推荐