Python泛型TypeVar应用:装饰器自动绑定Task泛型类型问题
问题描述
我正在构建一个适配Python typing的类装饰器,现有代码如下:
from typing import TypeVar, Generic, List, Type ExecutorType = TypeVar("ExecutorType") class Task(Generic[ExecutorType]): _executor: ExecutorType pass TaskType = TypeVar("TaskType", bound=Task) ChildTaskType = TypeVar("ChildTaskType", bound=Task) ExecutorType = TypeVar("ExecutorType", bound='Executor') class Executor(Generic[TaskType]): _TASKS_CLASSES: List[Type[TaskType]] = [] @classmethod def task(cls: Type[ExecutorType]): def decorator(task_cls: Type[ChildTaskType]): cls._TASKS_CLASSES.append(task_cls) return task_cls return decorator class Checker(Executor): def checker_method(self): return "Check Method" pass
我希望无类型错误地编写如下装饰器代码:
@Checker.task() class Check(Task): def check_method(self): self._executor.checker_method()
但此时self._executor被推断为基类Executor类型,而非Checker,导致checker_method无法被识别。手动指定Task[Checker]可以解决该问题,但我想知道能否通过装饰器task的类型注解,让返回的类自动将泛型参数指定为当前的ExecutorType(即实现类似返回Type[ChildTaskType[ExecutorType]]的效果)。
解决方案
要实现这个需求,需要调整泛型参数的定义和装饰器的类型注解,让Executor和Task的泛型参数形成关联。修改后的代码如下:
from typing import TypeVar, Generic, List, Type, cast # 重新定义泛型参数,明确边界和关联关系 T_Executor = TypeVar("T_Executor", bound="Executor") T_Task = TypeVar("T_Task", bound="Task") class Task(Generic[T_Executor]): _executor: T_Executor class Executor(Generic[T_Task]): _TASKS_CLASSES: List[Type[T_Task]] = [] @classmethod def task(cls: Type[T_Executor]): def decorator(task_cls: Type[Task[object]]) -> Type[Task[T_Executor]]: # 用cast告诉类型检查器,返回的Task类的泛型参数是当前Executor类型 annotated_task_cls = cast(Type[Task[T_Executor]], task_cls) cls._TASKS_CLASSES.append(annotated_task_cls) return annotated_task_cls return decorator class Checker(Executor): def checker_method(self) -> str: return "Check Method" # 现在使用装饰器时,无需手动指定Task[Checker] @Checker.task() class Check(Task): def check_method(self) -> None: # self._executor会被正确推断为Checker类型 self._executor.checker_method()
关键改动说明:
- 重命名泛型参数(如
T_Executor、T_Task)避免重复定义,增强可读性 - 在装饰器内部,通过
cast将传入的Task类强制标注为绑定当前ExecutorType的泛型类,让类型检查器能够正确推断self._executor的类型 - 调整
Executor的泛型参数关联,确保_TASKS_CLASSES存储的是绑定了对应Executor类型的Task子类
这样修改后,Check类无需手动指定Task[Checker],self._executor会自动被推断为Checker类型,checker_method可以正常被识别,且不会出现类型错误。
内容的提问来源于stack exchange,提问作者HenriChab
相关产品推荐
相关产品推荐

