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

Python中实现将dataclass属性转为Optional[List[X]]的类工厂

解决方案

要实现make_lister函数,核心是通过dataclasses模块提供的工具获取原数据类的字段信息,再动态生成符合要求的新类。以下是完整实现:

from dataclasses import dataclass, fields
from typing import Optional, List, Type
from dataclasses_json import DataClassJsonMixin
from datetime import datetime

@dataclass
class SrcClass(DataClassJsonMixin):
    number: int
    name: str
    at: datetime

def make_lister(src_cls: Type) -> Type:
    # 获取原数据类的所有字段信息
    src_fields = fields(src_cls)
    
    # 构建新类的字段字典:键为复数属性名,值为(新类型, 默认值)
    new_class_fields = {}
    for field in src_fields:
        # 生成复数属性名(基础规则:末尾加s,特殊词可扩展映射表)
        plural_field_name = field.name + "s"
        # 构造新类型:Optional[List[原字段类型]]
        new_field_type = Optional[List[field.type]]
        # 设置默认值为None,符合Optional类型的使用场景
        new_class_fields[plural_field_name] = (new_field_type, None)
    
    # 动态创建新类,指定类名、基类(仅继承DataClassJsonMixin)
    lister_class = type(
        f"{src_cls.__name__}Lister",
        (DataClassJsonMixin,),
        new_class_fields
    )
    
    # 将动态类转换为dataclass并返回
    return dataclass(lister_class)

# 生成目标类
SrcClassLister = make_lister(SrcClass)

关键细节说明

  1. 获取原数据类字段:
    使用dataclasses.fields(src_cls)可以提取原数据类的所有字段元信息,每个字段对象包含name(属性名)、type(字段类型)等核心信息,这是实现类型转换的基础。

  2. 复数属性名生成:
    示例中使用简单的末尾加s规则,若需要处理特殊复数形式(如child→children),可以扩展一个映射表:

    plural_mapping = {"child": "children", "person": "people"}
    plural_field_name = plural_mapping.get(field.name, field.name + "s")
    
  3. 类型转换:
    通过Optional[List[field.type]]将原字段类型X转换为允许为空的列表类型,满足过滤规格类接收值列表的需求。

  4. 动态创建类:
    利用Python内置的type函数动态生成类,参数分别为:

    • 新类名:原类名拼接Lister
    • 基类元组:仅指定DataClassJsonMixin
    • 类属性:包含新字段的类型注解和默认值(dataclass会自动识别这些属性并生成对应的字段)

验证测试

运行以下代码可以验证生成的类是否符合预期:

# 打印类的注解信息
print(SrcClassLister.__annotations__)
# 输出:
# {'numbers': typing.Optional[typing.List[int]], 'names': typing.Optional[typing.List[str]], 'ats': typing.Optional[typing.List[datetime]]}

# 实例化并序列化测试
filter_spec = SrcClassLister(numbers=[1, 3, 5], names=["Alice", "Charlie"])
print(filter_spec.to_json())
# 输出:{"numbers": [1, 3, 5], "names": ["Alice", "Charlie"], "ats": null}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 18:48:38