如何基于构造函数签名指定Python泛型类型?
解决类型转换泛型函数的类型标注问题
你想要实现一个泛型类型转换函数,接受任何仅需单个参数即可实例化的类型(比如str、int或自定义类),但现有标注方式无法同时兼容类型对象传入和mypy类型检查。
你的初始尝试代码:
from typing import TypeVar T = TypeVar("T") # Annotation here def some_func(x: Type[T]) -> T: return x(do_something_else())
遇到的问题:
- 用
Callable[[Any], T]标注x时,无法传入str、int这类类型对象; - 用
Type[T]标注时,mypy会提示参数过多的错误。
解决方案:使用Protocol定义构造协议
通过typing.Protocol定义一个描述“可接受单个参数实例化”的类型协议,让类型变量绑定该协议,既能兼容内置类型和自定义类,又能让mypy正确识别构造函数的参数要求。
示例代码:
from typing import TypeVar, Protocol, Any # 定义协议:要求类型的__init__接受一个任意类型参数 class OneArgConstructible(Protocol): def __init__(self, arg: Any) -> None: ... # 绑定协议,限制T必须符合该构造规则 T = TypeVar("T", bound=OneArgConstructible) def do_something_else() -> Any: # 示例实现,返回任意类型值 return "sample_data" def some_func(x: type[T]) -> T: return x(do_something_else()) # 测试验证 result_str: str = some_func(str) result_int: int = some_func(int) class CustomClass: def __init__(self, arg: Any) -> None: self.value = arg result_custom: CustomClass = some_func(CustomClass)
说明
- 协议
OneArgConstructible明确了类型必须具备接受单个参数的构造方法; TypeVar通过bound参数限定T的范围,确保传入的类型符合构造规则;- 若需要更严格的参数类型(比如要求构造参数是
str),只需修改协议中arg的类型标注即可。
内容的提问来源于stack exchange,提问作者Woody1193
相关产品推荐
相关产品推荐

