跳过正文
  1. Teches/
  2. 程序语言/
  3. python/
  4. 概念基础/

3.12高级类型参数

·393 字·2 分钟
目录

Python 3.12 通过 PEP 695 引入了更强大的高级类型参数机制,包括 可变类型参数(*Ts参数规格(**P,用于处理复杂泛型场景(如可变参数函数、回调函数类型等)。以下是对它们的详细解析:


1. 可变类型参数(*Ts
#

用途
#

表示一组不定数量的类型参数,类似 *args 的泛型版本。常用于:

  • 泛型元组或可变长度容器
  • 函数参数的类型标注(如 *args: *Ts

语法与示例
#

</> python
 1from typing import Tuple
 2
 3# 定义泛型元组,第一个元素为 str,其余元素类型可变
 4type LabeledTuple[*Ts] = tuple[str, *Ts]  # PEP 695 语法
 5
 6# 使用
 7x: LabeledTuple[int, float] = ("id", 42, 3.14)  # 等效于 tuple[str, int, float]
 8y: LabeledTuple[bool] = ("flag", True)          # 等效于 tuple[str, bool]
 9
10# 函数中的可变参数类型
11def zip[*T](*args: *T) -> list[tuple[*T]]:  # 模拟内置 zip 的类型
12    return list(zip(*args))

关键点
#

  • *Ts 表示类型元组,可匹配任意数量的类型参数。
  • 运行时会被擦除为 tuple,仅静态类型检查器(如 mypy)会验证类型安全性。
  • 与传统 TypeVarTuple 等效(Python 3.11 之前需用 from typing import TypeVarTuple)。

2. 参数规格(**P
#

用途
#

描述函数的参数类型和返回值类型,用于泛型高阶函数(如装饰器、回调函数)。类似 **kwargs 的泛型扩展。

语法与示例
#

</> python
 1from typing import Callable
 2
 3# 定义泛型回调函数类型:参数类型为 **P,返回值为 int
 4type IntFunc[**P] = Callable[P, int]  # PEP 695 语法
 5
 6# 使用
 7def foo(x: str, y: float) -> int:
 8    return len(x) + int(y)
 9
10f: IntFunc[str, float] = foo  # 匹配参数 (str, float) -> int
11
12# 泛型装饰器
13def logger[**P, R](func: Callable[P, R]) -> Callable[P, R]:
14    def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
15        print(f"Calling {func.__name__}")
16        return func(*args, **kwargs)
17    return wrapper

关键点
#

  • **P 表示参数规格(Parameter Specification),捕获函数的参数类型(位置参数和关键字参数)。
  • 与传统 ParamSpec 等效(Python 3.11 之前需用 from typing import ParamSpec)。
  • 结合 P.argsP.kwargs 可精确描述函数签名。

3. 高级组合用法
#

(1) 泛型可变参数函数
#

</> python
1def call_with_args[*Ts, R](func: Callable[[*Ts], R], *args: *Ts) -> R:
2    return func(*args)
3
4# 使用
5def add(a: int, b: int) -> int:
6    return a + b
7
8call_with_args(add, 1, 2)  # Ts 推断为 (int, int), R 为 int

(2) 泛型装饰器工厂
#

</> python
 1type Decorator[**P, R] = Callable[[Callable[P, R]], Callable[P, R]]
 2
 3def retry[**P, R](max_attempts: int) -> Decorator[P, R]:
 4    def decorator(func: Callable[P, R]) -> Callable[P, R]:
 5        def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
 6            for _ in range(max_attempts):
 7                try:
 8                    return func(*args, **kwargs)
 9                except Exception:
10                    continue
11            raise RuntimeError("All attempts failed")
12        return wrapper
13    return decorator
14
15@retry(max_attempts=3)
16def fetch_data(url: str) -> dict:
17    import requests
18    return requests.get(url).json()

4. 与传统语法的对比
#

特性Python 3.12 新语法旧语法(3.11 及之前)
可变类型参数type Tuple[*Ts] = ...Ts = TypeVarTuple("Ts")
参数规格type Func[**P] = ...P = ParamSpec("P")
类型约束[*Ts: (int, str)]Ts = TypeVarTuple("Ts", int, str)

5. 注意事项
#

  1. 静态类型检查依赖
    • 需使用支持 PEP 695 的工具链(如 mypy 1.11+、pyright)。
    • 运行时无类型信息(类型擦除)。
  2. 性能影响
    • 泛型类型注解不影响运行时性能,但复杂嵌套可能增加静态检查时间。
  3. 兼容性
    • 旧代码可逐步迁移,新旧语法混用需确保类型检查器兼容。

总结
#

Python 3.12 的 *Ts**P 提供了更直观的泛型抽象能力:

  • *Ts:用于可变长度类型序列(如元组、*args)。
  • **P:用于精确描述函数参数类型(如装饰器、回调)。
  • 设计目标:减少 typing 模块的样板代码,提升代码可读性,同时保持与静态类型检查器的深度集成。