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

Python是否有TypeScript中Pick类型的等效实现?

在Python中实现TypeScript风格的Pick与Add类型功能

实现Pick函数

我们可以利用dataclasses.make_dataclass动态生成仅包含指定字段的数据类,同时保留原类型的类型提示:

from dataclasses import dataclass, make_dataclass
from typing import TypeVar, Tuple, Type, get_type_hints

T = TypeVar('T')

def Pick(cls: Type[T], fields: Tuple[str, ...]) -> Type:
    # 获取原类的类型提示
    type_hints = get_type_hints(cls)
    
    # 检查指定字段是否存在于原类中
    missing_fields = [f for f in fields if f not in type_hints]
    if missing_fields:
        raise ValueError(f"字段 {missing_fields} 不存在于 {cls.__name__} 中")
    
    # 筛选出目标字段及其类型
    selected_fields = [(field, type_hints[field]) for field in fields]
    
    # 生成新的数据类
    return make_dataclass(f"{cls.__name__}Pick", selected_fields)

实现Add函数

类似地,我们可以生成包含原类所有字段及新增字段的数据类:

def Add(cls: Type[T], new_fields: dict[str, type]) -> Type:
    type_hints = get_type_hints(cls)
    
    # 检查新增字段是否与原类字段冲突
    conflicting_fields = [f for f in new_fields if f in type_hints]
    if conflicting_fields:
        raise ValueError(f"字段 {conflicting_fields} 已存在于 {cls.__name__} 中")
    
    # 合并原字段与新增字段
    combined_fields = list(type_hints.items()) + list(new_fields.items())
    
    # 生成新的数据类
    return make_dataclass(f"{cls.__name__}Add", combined_fields)

使用示例

from dataclasses import dataclass
from typing import List

@dataclass
class Foo:
    x: int
    y: float
    z: str

# 从Foo中挑选x和y字段生成Bar类
Bar = Pick(Foo, ('x', 'y'))
bar = Bar(1, 2.0)
print(bar)  # 输出: FooPick(x=1, y=2.0)

# 给Foo添加w字段生成Baz类
Baz = Add(Foo, {'w': List[int]})
baz = Baz(1, 2.0, '3', w=[1, 2, 3])
print(baz)  # 输出: FooAdd(x=1, y=2.0, z='3', w=[1, 2, 3])

类型安全与mypy支持

上述实现在运行时完全类型安全,但mypy的静态分析对动态生成的类支持有限。若需要mypy完全识别生成类的字段类型,可以:

  • 为生成的类添加显式协议注解:
    from typing import Protocol
    
    class BarProtocol(Protocol):
        x: int
        y: float
    
    Bar: Type[BarProtocol] = Pick(Foo, ('x', 'y'))
    
  • 使用pydantic库的create_model方法,它对动态模型的类型推断支持更完善:
    from pydantic import create_model
    
    Bar = create_model('Bar', __base__=Foo, include={'x', 'y'})
    Baz = create_model('Baz', __base__=Foo, w=(List[int], []))
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 19:25:19