当前位置:首页 > 文章列表 > 文章 > python教程 > Python TypedDict 怎样标记部分必填字段

Python TypedDict 怎样标记部分必填字段

来源:17golang原创 2026-10-18 14:10:35 0浏览 收藏

Python TypedDict 中只让部分字段必填,可以使用 total=False 配合 Required[T];如果大部分字段必填,则保留默认 total=True,只给可缺省字段加 NotRequired[T]。这些标记约束的是键是否必须存在,不能代替运行时输入校验,也不等同于值是否允许 None。

以下用上传元数据 UploadSpec 展示最小写法与变体,不涉及实际文件上传。示例面向 Python 3.11 及以上。官方文档:https://docs.python.org/3/library/typing.html#typing.TypedDict;Required 与 NotRequired 的设计说明见 https://peps.python.org/pep-0655/。

先写出只有标识必填的最小声明

from typing import Required, TypedDict


class UploadSpec(TypedDict, total=False):
    # 即使其余字段可缺省,object_id 也必须存在且为字符串。
    object_id: Required[str]
    caption: str
    expires_at: str | None


# 只有标识也满足契约;不需要为可缺省键补 None。
minimal: UploadSpec = {"object_id": "asset-17"}

object_id 是必填字符串;caption 可以整个键不出现,出现时应为字符串;expires_at 也可以不出现,出现时允许字符串或 None。这里的约束供静态类型工具理解,不是字典创建时自动执行的验证规则。

可以把这份声明当作三个位置的契约:object_id 属于必填键,caption 与 expires_at 属于可缺省键。total=False 提供本类声明字段的缺省规则,Required 在单个字段上明确覆盖它。

UploadSpec的必填键、可缺省键和total规则关系
图1:字段契约静态说明图。分组区分声明规则与三个字段,连线表示规则归属,不是执行顺序或运行截图。

把键是否存在和取值是否为空分开

两个维度要分别回答:字典里是否必须有这个键?有键时允许什么值?在默认 total=True 的 TypedDict 中,expires_at: str | None 仍然要求 expires_at 存在,只是值可以为 None;它不能表达“键可以不传”。

字段声明(默认 total=True)键可缺省值可为 None
value: str否否
value: str | None否是
value: NotRequired[str]是否
value: NotRequired[str | None]是是

Optional[str] 的含义与 str | None 相同,并不会让键变成可缺省。对于部分更新一类接口,“不提供字段”可能代表保持原设置,“提供 None”可能代表清空设置,但这只是可选择的业务约定,TypedDict 本身不赋予这两种操作任何服务端含义。

按必填字段比例选择另一种写法

from typing import NotRequired, TypedDict


class UploadSpec(TypedDict):
    # 默认 total=True,未特别标记的键是必填键。
    object_id: str
    caption: NotRequired[str]
    expires_at: NotRequired[str | None]

这份 UploadSpec 与前面的字段契约相同,只是从“默认全可缺省,单独声明必填”换成“默认全必填,单独声明可缺省”。实际项目选一种更贴近字段比例的写法即可,不必在同一模块里重复定义同名类型。

Required 和 NotRequired 只用于 TypedDict 的字段注解;不要把它们当普通函数参数的必填声明,也不要嵌套成 Required[NotRequired[str]]。函数参数是否必须传入,应由函数签名与默认参数决定。

读取可缺省字段时保留存在性判断

下面是一段可独立保存的完整示例。describe_expiry 只描述元数据,没有请求外部服务,也不解析日期、设置过期任务或更改存储系统。

from typing import NotRequired, TypedDict


class UploadSpec(TypedDict):
    # 必填标识与两项可缺省元数据分别声明。
    object_id: str
    caption: NotRequired[str]
    expires_at: NotRequired[str | None]


def describe_expiry(spec: UploadSpec) -> str:
    # 先判断键存在,避免把“未提供”与“显式清空”混为一谈。
    if "expires_at" not in spec:
        return "未提供过期设置"
    expiry = spec["expires_at"]
    if expiry is None:
        return "显式清空过期设置"
    return f"过期时间:{expiry}"


omitted: UploadSpec = {"object_id": "asset-17"}
cleared: UploadSpec = {"object_id": "asset-18", "expires_at": None}
scheduled: UploadSpec = {
    "object_id": "asset-19",
    "expires_at": "2027-01-10T08:00:00Z",
}
print(describe_expiry(omitted))
print(describe_expiry(cleared))
print(describe_expiry(scheduled))

这里用 "expires_at" in spec 区分缺键,再判断值是否为 None。若直接 spec["expires_at"],缺键时普通字典仍可能抛 KeyError;如果直接 spec.get("expires_at"),缺键与值为 None 都会得到 None,无法保留本例所需区别。

expires_at存在性与值域的静态关系
图2:存在性和值域说明图。缺键、None 与字符串分别是可缺省字段的不同状态;图中关系只解释 describe_expiry 的判断依据,不是实测输出。

将完整片段保存为 typed_metadata.py 后,读者可在 Python 3.11 及以上运行:

# 只运行字典读取示例,不执行上传操作。
python3 typed_metadata.py

本文没有执行示例。按三个输入推导的预期文本如下;它只是运行时函数行为,不代表静态类型检查已经通过:

未提供过期设置
显式清空过期设置
过期时间:2027-01-10T08:00:00Z

明确版本与运行时边界

Python 3.11 起可以从 typing 导入 Required 与 NotRequired。维护更早版本时,需采用兼容的 typing_extensions,并按其支持范围配置;PEP 655 特别提醒老版本方案中 TypedDict 也应从 typing_extensions 导入,不要随意混用新限定符和旧 typing.TypedDict。本文不安装依赖或运行类型检查工具。

TypedDict 的值在运行时仍是普通字典。它不会替你拒绝缺少 object_id 的外部 JSON,不会检查 object_id 是不是字符串,也不会补 caption 的默认值。来自网络、文件等不可信输入,需要另设运行时解析和校验入口,再交给声明了契约的业务函数;单纯加注解或做类型断言不能把不合法数据变合法。

静态工具的诊断文字和部分读取提示会因工具及配置不同而变化,不能把一次 python3 执行成功当成类型约束已验证。反过来,类型符合声明也不意味着字符串就是有效日期或真实对象标识。

常见问题速查

NotRequired 会自动给字段设置默认值吗?

不会,它只说明键允许不出现。需要默认值时,应在读取或构造逻辑里显式定义,并决定是否要区分缺键与 None。

外层字段必填,内部字段也会跟着必填吗?

不会递归套用。嵌套值如果又是一个 TypedDict,应由内部类型单独定义其字段规则;外层 Required 只约束那个外层键。

子类写 total=False 会把继承的必填键全部变为可缺省吗?

不会,total 作用于当前类体新声明的字段,不会批量改写继承字段的既有必填性。避免通过重新声明同名字段强行改变契约。

最小选择规则是:少数必填用 total=False 加 Required,少数可缺省用默认 total 加 NotRequired;允许 None 则另写值联合类型。把这两层分清,部分必填字段的注解就不必依赖模糊的“可选”一词。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Python asyncio.Queue 关闭后怎样结束消费者Python asyncio.Queue 关闭后怎样结束消费者
上一篇
Python asyncio.Queue 关闭后怎样结束消费者
Python LiteralString 怎样约束拼接后的字符串
下一篇
Python LiteralString 怎样约束拼接后的字符串
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    523次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    580次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    607次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    557次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    377次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码