Python 数据建模:dataclass、TypedDict、Literal 与 LangGraph State 总结

Python 数据建模:dataclass、TypedDict、Literal 与 LangGraph State 总结
文章目录一、dataclass 与 TypedDict 通用对比二、Literal 类型三、LangGraph 中的 State 用法调用时必须提供初始值四、综合示例dataclass 与 TypedDict 的通用区别、Literal 类型以及它们在 LangGraph 中作为 State 时的具体用法与差异。一、dataclass 与 TypedDict 通用对比核心区别 特性 dataclass TypedDict 引入版本 Python 3.7 Python 3.8运行时实体 真正的类可实例化 普通 dict类型构造器 数据访问 属性访问 (obj.x) 键访问 (d[“x”])主要用途 封装数据 行为 为字典提供精确类型提示 默认值 支持… 或 field() 不直接支持需用NotRequired/totalFalse 继承 完整类继承字段自动合并 支持 TypedDict 继承类型检查 检查实例属性类型 检查字典键是否存在及值类型代码示例fromdataclassesimportdataclassfromtypingimportTypedDictdataclassclassPointDC:x:inty:intclassPointTD(TypedDict):x:inty:intdcPointDC(1,2)td:PointTD{x:1,y:2}print(dc.x)# 属性访问 ✅print(td[x])# 键访问 ✅如何选择用 dataclass需要对象语义、方法、post_init校验、默认值、比较操作。用 TypedDict数据本质是字典JSON / API 响应仅需静态类型提示不改运行时结构。二、Literal 类型概念Literal 用于精确限定取值为特定常量如 Literal[“open”, “closed”]仅在静态类型检查mypy、pyright中生效运行时无强制约束。与 Enum 对比方案 本质 适用场景Literal 类型注解 少量固定常量、字符串/数字标志Enum 枚举类 需遍历、运行时强类型、自文档化在数据类中的结合使用fromtypingimportLiteral,TypedDictfromdataclassesimportdataclassdataclassclassUser:role:Literal[admin,user,guest]classConfig(TypedDict):env:Literal[dev,prod]debug:bool三、LangGraph 中的 State 用法LangGraph 允许使用 dataclass 或 TypedDict 定义 State。两者在节点node返回值上的行为完全一致。3.1 Node 返回值通用规则Node 函数接收 State 作为参数类型为 dataclass 实例或 TypedDict 字典。必须返回一个 dict且该 dict 表示增量更新不必包含全部字段。框架根据 reducer 合并回原 State未返回的字段保持原值。若返回不存在的键或空 dict无有效键会触发 InvalidUpdateError。def node(state: State) - dict:return {“count”: state.count 1} # 只更新 count其他字段保留3.2 dataclass 作为 State定义与默认值fromdataclassesimportdataclass,fieldfromlanggraph.graphimportStateGraphdataclassclassState:step:int0logs:list[str]field(default_factorylist)Reducer 标注fromtypingimportAnnotatedfromoperatorimportadddataclassclassState:logs:Annotated[list[str],add]field(default_factorylist)节点读写读state.step写返回 {“step”: new_value}优势与场景默认值书写自然尤其适合 list/dict 字段。属性访问带 IDE 补全重构安全。支持post_init做状态校验。适合字段较多、有合并逻辑的内部业务图。3.3 TypedDict 作为 State定义与默认值fromtypingimportTypedDict,AnnotatedfromoperatorimportaddclassState(TypedDict):step:intlogs:Annotated[list[str],add]调用时必须提供初始值graph.invoke({“step”: 0, “logs”: []})Python 3.11 可用 NotRequired 实现可选但仍非真正的默认值。节点读写读state[“step”]写返回 {“step”: new_value}优势与场景原生字典JSON 序列化友好。与 API / 外部 JSON 响应结构自然对齐。Checkpoint 存为人类可读的纯 dict。3.4 对比总结表LangGraph 场景维度 dataclass State TypedDict State节点入参类型 dataclass 实例 dict 子类读取方式 state.field state[“field”]默认值 天然支持 需手动传初始值或 NotRequiredreducer 写法 Annotated field() Annotated 直接标在类型上序列化 pickle默认 checkpoint 原生 dictJSON 友好运行时校验post_init支持 无3.5 实践建议优先用 dataclass字段多、需默认值、有 list/dict reducer、偏好 . 访问。优先用 TypedDict状态即 JSON、需可读 checkpoint、字段少且愿每次传全初始值。两者 node 返回值均为增量 dict都不必返回全部字段。四、综合示例fromdataclassesimportdataclass,fieldfromtypingimportAnnotated,Literalfromoperatorimportaddfromlanggraph.graphimportStateGraphdataclassclassAppState:count:int0status:Literal[idle,run]idlehistory:Annotated[list[int],add]field(default_factorylist)defincrement(state:AppState)-dict:return{count:state.count1,history:[state.count1]}graphStateGraph(AppState)graph.add_node(inc,increment)graph.set_entry_point(inc)appgraph.compile()resultapp.invoke({})print(result)