能否以泛型类的TypeVar为上界定义新TypeVar,实现方法精确类型返回?
解决方案:让泛型方法返回参数的精确类型并保留上界约束
通用泛型类的实现方式
要让泛型类的方法返回参数的精确类型,同时受类的泛型上界限制,需要在方法内部定义一个方法级别的TypeVar,并将其绑定到类的泛型参数。这样既保证参数属于泛型上界的子类型,又能让类型检查器保留参数的具体类型信息。
修正后的MyClass实现:
from typing import TypeVar, Generic T = TypeVar('T') class MyClass(Generic[T]): # 定义方法专属的TypeVar,上界为类的泛型参数T MethodT = TypeVar('MethodT', bound=T) def method(self, obj: MethodT) -> MethodT: # 执行逻辑 return obj
效果验证
instance: MyClass[A] = MyClass() instance.method(A()) # 返回类型:A ✔️ instance.method(B()) # 返回类型:B ✔️ instance.method(C()) # 返回类型:C ✔️ instance.method(123) # 类型检查错误:int不是A的子类型 ✔️
实际用例:可调用对象注册表的修正
针对你的注册表实现,需要解决两个核心问题:
- 让装饰器返回函数的精确类型而非泛型协议类型;
- 修复协议定义导致的关键字参数调用限制。
步骤1:修正Registry类的类型注解
在Registry类的__call__方法中定义方法级TypeVar,绑定到类的泛型参数CallableSignaturesT,同时处理注册表列表的类型兼容问题(若Mypy报错,可使用cast转换类型):
from typing import TypeVar, Generic, Protocol, Any, cast class AnyCallable(Protocol): def __call__(self, *__args: Any, **__kwargs: Any) -> Any: ... CallableSignaturesT = TypeVar('CallableSignaturesT', bound=AnyCallable, default=AnyCallable) class Registry(Generic[CallableSignaturesT]): def __init__(self) -> None: self._registry: list[CallableSignaturesT] = [] # 方法级TypeVar,绑定到类的泛型参数 FuncT = TypeVar('FuncT', bound=CallableSignaturesT) def __call__(self, func: FuncT) -> FuncT: # 用cast解决列表的不变性限制(子类型实例存入父类型列表) self._registry.append(cast(CallableSignaturesT, func)) return func
步骤2:修正可调用协议的参数定义
原协议中使用__arg1(位置-only参数前缀)导致Mypy限制关键字参数调用,需改为普通参数名:
class MyCallable(Protocol): def __call__(self, arg1: int, arg2: str, *__args: Any, **__kwargs: Any) -> Any: ...
步骤3:使用验证
my_registry: Registry[MyCallable] = Registry() @my_registry def my_callable(arg1: int, arg2: str, some_arg_from_workflow_dict: bool): return f"{arg1}, {arg2}, {some_arg_from_workflow_dict}" # 调用验证:类型检查器识别所有参数,允许关键字调用 ✔️ my_callable(arg1=1, arg2='str', some_arg_from_workflow_dict=True) # 错误验证:不符合参数要求的函数会被拦截 ✔️ @my_registry def invalid_func(arg1: str): # Mypy报错:参数类型不匹配MyCallable协议 pass
内容的提问来源于stack exchange,提问作者Gygabrain
相关产品推荐
相关产品推荐

