You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让类型变量同时用于代码逻辑与类型注解?

解决方案

你遇到的问题核心是Python的类型擦除机制——泛型类型变量T在运行时不会保留具体的类型信息,所以直接在func里用T(42)会报错。不过可以通过自动提取子类的泛型参数来避免重复设置_type属性,具体实现如下:

实现代码

import typing
from typing import TypeVar, Generic, get_args

T = TypeVar('T')

class Base(Generic[T]):
    _type: typing.Type[T]

    def __init_subclass__(cls) -> None:
        # 从子类的原始泛型基类中提取实际类型参数
        for base in cls.__orig_bases__:
            origin = typing.get_origin(base)
            if origin is Base:
                cls._type = get_args(base)[0]
                break
        else:
            raise TypeError("子类必须继承带具体类型参数的Base类")

    def func(self) -> T:
        return self._type(42)

# 子类只需指定泛型参数,无需手动设置_type
class A(Base[int]):
    pass

class B(Base[str]):
    pass

# 测试验证
a_instance = A()
print(a_instance.func())  # 输出: 42 (类型为int)
print(type(a_instance.func()))  # 输出: <class 'int'>

b_instance = B()
print(b_instance.func())  # 输出: "42" (类型为str)
print(type(b_instance.func()))  # 输出: <class 'str'>

原理说明

  1. __init_subclass__钩子:Python 3.6及以上版本支持这个钩子,当子类继承Base时会自动执行该方法,省去手动初始化的步骤。
  2. __orig_bases__属性:这个属性保存了子类继承的原始泛型基类(比如Base[int]),而非Python内部处理后的包装类。
  3. get_origin和get_args工具:get_origin用于获取泛型的原始类(比如从Base[int]中拿到Base),get_args则提取出泛型参数(比如从Base[int]中拿到int)。

这样修改后,子类只需要像Base[int]这样指定泛型参数,_type属性会被自动设置,完全避免了重复代码。

内容的提问来源于stack exchange,提问作者eepp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 11:35:19