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

Python如何基于已有类型生成全字段为Optional的新类型

自动生成全字段Optional类型的实现方案

你可以通过Python类型注解的内省能力,结合动态类创建逻辑实现需求,自动将原类所有非Optional字段转为Optional类型,且不会给已为Optional的字段生成嵌套Optional。

核心实现代码

首先编写通用的类生成函数,兼容普通类、dataclass、Pydantic模型等所有带类型注解的Python类:

from typing import Optional, Union, get_type_hints, get_origin, get_args
import types

def optionalize_class_fields(original_cls: type, suffix: str = "Query") -> type:
    new_cls_name = f"{original_cls.__name__}{suffix}"
    # 提取原类所有字段的类型注解
    original_fields = get_type_hints(original_cls)
    new_annotations = {}

    for field_name, field_type in original_fields.items():
        # 判断字段是否已经是Optional(即Union包含None类型)
        type_origin = get_origin(field_type)
        type_args = get_args(field_type)
        if type_origin is Union and type(None) in type_args:
            # 已是Optional,直接保留原类型
            new_annotations[field_name] = field_type
        else:
            # 非Optional字段包装为Optional
            new_annotations[field_name] = Optional[field_type]
    
    # 动态创建新类,如需保留原类方法可保留继承,不需要可改为继承object
    new_cls = types.new_class(new_cls_name, (original_cls,))
    new_cls.__annotations__ = new_annotations
    return new_cls

使用方式

直接调用函数即可生成你需要的SomeResourceQuery类,无需手动编写重复代码:

class SomeResource:
    id: int
    name: str
    # 已为Optional的字段会被原样保留
    remark: Optional[str] = None

# 一行生成目标类
SomeResourceQuery = optionalize_class_fields(SomeResource)

# 验证类型注解结果
from typing import get_type_hints
print(get_type_hints(SomeResourceQuery))
# 输出:{'id': typing.Optional[int], 'name': typing.Optional[str], 'remark': typing.Optional[str]}

仓储层的使用完全符合你的预期:

class SomeResourceRepository:
    def get_one_or_none(self, query: SomeResourceQuery) -> Optional[SomeResource]:
        # 业务查询逻辑,传None的字段代表不作为过滤条件
        pass

版本兼容说明

如果你使用Python 3.10+的| None语法代替Optional写法,只需要修改类型判断逻辑,兼容新的联合类型写法即可:

# 放在类型判断的位置,替换原有if条件即可
import sys
if sys.version_info >= (3, 10):
    import types as py_types
    is_optional = (type_origin is Union or type_origin is py_types.UnionType) and type(None) in type_args
else:
    is_optional = type_origin is Union and type(None) in type_args

if is_optional:
    new_annotations[field_name] = field_type
else:
    new_annotations[field_name] = field_type | None # 也可继续用Optional[field_type]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 06:18:21