如何为装饰器所用的泛型类型创建类型别名?
解决方案
兼容全版本方案(Python 3.8+ 支持,适配mypy严格模式)
使用泛型Protocol定义可调用类型的签名,会自动绑定泛型参数T,不会出现未绑定报错:
import unittest from typing import TypeVar, Callable, Protocol T = TypeVar("T", bound=unittest.TestCase) # 定义泛型可调用协议作为类型别名 class TestDecorator(Protocol[T]): def __call__(self, func: Callable[[T], None]) -> Callable[[T], None]: ...
使用时直接标注即可,完全符合--strict模式的检查要求:
my_decorate: TestDecorator[T] = decorate
Python 3.12+ 简化方案
PEP 695 引入了原生泛型类型别名语法,写法更简洁:
import unittest from typing import TypeVar, Callable T = TypeVar("T", bound=unittest.TestCase) type TestDecorator[T] = Callable[[Callable[[T], None]], Callable[[T], None]] # 使用方式和上面一致 my_decorate: TestDecorator[T] = decorate
原写法报错原因
Python 3.12 之前的普通类型别名不会自动将内部用到的TypeVar识别为泛型参数,别名中的T属于自由类型变量:
- 在函数参数中使用时,
T可以被函数本身的泛型声明绑定,所以可以正常工作 - 直接给变量标注时无上下文绑定
T,就会抛出未绑定错误 - 省略泛型参数直接写
TestDecorator会被类型检查器判定为缺少参数,同时丢失泛型校验能力
内容的提问来源于stack exchange,提问作者Zulan
相关产品推荐
相关产品推荐

