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

为适配Dataclass的StdVectorList类添加类型提示以约束vec_type

为StdVectorList添加类型提示约束vec_type的解决思路

我实现了一个继承自MutableSequence的Python类StdVectorList,它封装了CERN ROOT的C++ std::vector,支持用Python列表初始化。但类的元素类型是通过初始化参数vec_type(字符串,比如"float")指定的,导致实例的类型信息无法被类型检查工具识别,也无法约束用户传入合法的vec_type值。以下是几种可行的解决思路:

原类初始化代码:

from collections.abc import MutableSequence
import ROOT

class StdVectorList(MutableSequence):
    """A python list interface to ROOT's std::vector"""
    def __init__(self, vec_type, value=[]):
        """
        Args:
            vec_type: C++ type for the std::vector (eg. "float", "string", etc.)
            value: list with which to init the vector
        """
        self._vector = ROOT.vector(vec_type)(value)
        #: C++ type for the std::vector (eg. "float", "string", etc.)
        self.vec_type = vec_type

方案1:用Literal限定合法的vec_type字符串

直接用typing.Literal列出所有允许的vec_type取值,让类型检查工具(如mypy、Pyright)强制约束用户只能传入指定字符串,同时结合Generic关联对应的Python元素类型,让实例的类型信息可被识别。

修改后的代码:

from collections.abc import MutableSequence
from typing import Literal, Generic, TypeVar
import ROOT

# 定义允许的C++类型字符串集合
AllowedVecType = Literal["float", "int", "string", "double"]
# 绑定对应的Python元素类型
T = TypeVar("T", float, int, str, float)

class StdVectorList(MutableSequence, Generic[T]):
    """A python list interface to ROOT's std::vector"""
    def __init__(self, vec_type: AllowedVecType, value: list[T] = []):
        """
        Args:
            vec_type: C++ type for the std::vector (eg. "float", "string", etc.)
            value: list with which to init the vector
        """
        self._vector = ROOT.vector(vec_type)(value)
        self.vec_type: AllowedVecType = vec_type

# 使用示例
a = StdVectorList("float")  # 合法,类型检查通过
b = StdVectorList("int")    # 合法
# c = StdVectorList("char") # 类型检查工具会报错,提示不在允许范围内

方案2:通过Generic+工厂函数隐藏字符串参数

定义与Python类型绑定的泛型类,用工厂函数自动完成Python类型到C++类型字符串的映射,用户无需手动传入vec_type字符串,实例的类型信息更直观。

修改后的代码:

from collections.abc import MutableSequence
from typing import Generic, TypeVar, overload, Literal
import ROOT

T = TypeVar("T", float, int, str, float)
# 建立Python类型到C++类型字符串的映射表
TYPE_MAP = {
    float: "float",
    int: "int",
    str: "string",
    float: "double"
}

class StdVectorList(MutableSequence, Generic[T]):
    """A python list interface to ROOT's std::vector"""
    def __init__(self, vec_type: str, value: list[T] = []):
        self._vector = ROOT.vector(vec_type)(value)
        self.vec_type = vec_type

# 重载工厂函数,支持两种调用方式
@overload
def create_std_vector(value: list[float] = [], /) -> StdVectorList[float]: ...
@overload
def create_std_vector(value: list[int] = [], /) -> StdVectorList[int]: ...
@overload
def create_std_vector(value: list[str] = [], /) -> StdVectorList[str]: ...
@overload
def create_std_vector(vec_type: Literal["float", "int", "string"], value: list = [], /) -> StdVectorList: ...

def create_std_vector(vec_type_or_value=None, value=[]):
    if isinstance(vec_type_or_value, list):
        # 从列表元素类型自动推断C++类型
        if not vec_type_or_value:
            raise ValueError("无法从空列表推断元素类型")
        elem_type = type(vec_type_or_value[0])
        vec_type = TYPE_MAP.get(elem_type)
        if not vec_type:
            raise TypeError(f"不支持的元素类型: {elem_type}")
        return StdVectorList(vec_type, vec_type_or_value)
    elif isinstance(vec_type_or_value, str):
        return StdVectorList(vec_type_or_value, value)
    else:
        raise ValueError("无效参数")

# 使用示例
a = create_std_vector("float")  # 仍支持手动传入类型字符串
b = create_std_vector([1.0, 2.0])  # 自动推断为float类型
c: StdVectorList[int] = create_std_vector([1,2,3])  # 类型标注清晰

方案3:用枚举类约束vec_type输入

定义枚举类统一管理合法的vec_type选项,用户必须传入枚举成员,彻底避免字符串拼写错误,内部将枚举值转为对应的C++类型字符串。

修改后的代码:

from collections.abc import MutableSequence
from enum import Enum
from typing import Generic, TypeVar
import ROOT

class VectorType(Enum):
    FLOAT = "float"
    INT = "int"
    STRING = "string"
    DOUBLE = "double"

T = TypeVar("T", float, int, str, float)

class StdVectorList(MutableSequence, Generic[T]):
    """A python list interface to ROOT's std::vector"""
    def __init__(self, vec_type: VectorType, value: list[T] = []):
        """
        Args:
            vec_type: C++类型枚举
            value: 用于初始化的列表
        """
        self._vector = ROOT.vector(vec_type.value)(value)
        self.vec_type = vec_type.value

# 使用示例
a = StdVectorList(VectorType.FLOAT)  # 只能传入枚举成员
# b = StdVectorList("float") # 类型检查工具会报错,必须传入VectorType枚举

内容的提问来源于stack exchange,提问作者Lech Wiktor Piotrowski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 12:55:25