ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python 参数边界控制:用 `/` 与 `*` 严格隔离位置参数与关键字参数

Python 参数边界控制:用 `/` 与 `*` 严格隔离位置参数与关键字参数 文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载在 Python 中定义函数时默认情况下每个参数既可以按位置传入也可以按关键字namevalue传入甚至可以混合使用。但在设计公共 API、CLI 配置函数或需要保证调用方语义清晰时我们往往希望强制一部分参数只能按位置传入、另一部分只能按关键字传入。本文基于 til 仓库中的 strictly-separate-positional-and-keyword-arguments.md系统讲解如何用位置限定符/positional-only marker与关键字限定符*keyword-only marker在函数定义中建立严格的参数边界并给出可复现的代码示例、错误信息分析、类型检查器提示以及inspect层面的验证方法。默认的灵活传参方式位置与关键字随意混用通常情况下Python 函数参数既可以按位置传递也可以按关键字传递二者还能混用——唯一硬性约束是所有位置参数必须排在所有关键字参数之前。例如下面这个函数def describe(host, port, verbose): print(host, port, verbose)以下调用方式全部合法describe(localhost, 3000, True) # 全按位置 describe(hostlocalhost, port3000, verboseTrue) # 全按关键字 describe(localhost, 3000, verboseTrue) # 位置 关键字混用这种灵活性在日常脚本中很便利但它也带来一个现实问题调用方可以随意把host、port写成关键字形式函数内部一旦重命名参数外部调用就可能悄然失配。当参数语义对顺序高度敏感例如网络连接的目标地址与端口时我们更希望强制调用方按位置传入避免误用。两个标记符/与*的职责Python 的函数签名中内置了两个边界标记标记名称位置作用/positional-only marker参数列表中间或末尾位于其左侧的所有参数只能按位置传递*keyword-only marker参数列表中间或末尾位于其右侧的所有参数只能按关键字传递两个标记可以单独使用也可以像本篇主题那样组合使用从而把参数列表切成三段位置限定区 | 普通区位置/关键字皆可 | 关键字限定区。组合使用让connect的参数边界清晰可读原文档给出了一个非常典型的网络连接示例。connect函数的签名如下def connect(host, port, /, *, timeout30): print(fConnecting to #{host}:#{port}) print(f Timeout: {timeout}s) # ...逐段解读这条签名host与port位于/左侧因此必须按位置传入——这样连接目标在调用处始终以先主机、后端口的直观顺序出现timeout位于*右侧因此必须按关键字传入——它带有默认值30调用方不传时自动使用 30 秒传入时必须显式写成timeout20这样的形式。正确调用位置 关键字 connect(localhost, 3000, timeout20) Connecting to #localhost:#3000 Timeout: 20shost、port以位置传入timeout以关键字传入组合使用两种标记的效果立即可见。错误调用把位置限定参数当关键字用 connect(hostlocalhost, port4000) Traceback (most recent call last): File /Users/lastword/dev/misc/python-experiments/arguments.py, line 37, in module connect(hostlocalhost, port4000) TypeError: connect() got some positional-only arguments passed as keyword arguments: host, port第二次调用试图把host和port作为关键字参数传入立刻在运行时抛出TypeError错误信息明确告诉我们这两个参数是 positional-only arguments仅限位置参数却被以关键字形式传递了。错误信息中会精确列出违规的参数名这里是host, port便于快速定位调用方的问题。该报错信息已在 Python 3.12.10 环境下实测复现与文档记录完全一致。编辑器中的静态类型检查问题在运行前就被发现除了运行时TypeError这类误用还会在编辑器中以静态类型错误的形式提前暴露。原文档作者在编辑器中看到该行同时出现两个类型检查错误call-arg: Unexpected keyword argument port for connect以及针对host的同等报错。也就是说只要配合 Pyright 这类类型检查器仓库中相关的配置笔记包括 enable-pyright-type-checking-in-cursor.md、set-up-pyright-type-checking-in-github.md 以及 basedpyright-will-use-pyright-config.md在保存代码的瞬间就能看到call-arg诊断而不是等到 CI 或运行时才暴露。用inspect验证参数分类三种参数区间Python 标准库的inspect.signature可以从元数据层面验证每个参数的真实种类Parameter.kind这也是理解/与*底层语义最直接的手段。对上面的connect函数import inspect def connect(host, port, /, *, timeout30): pass sig inspect.signature(connect) print(sig) # (host, port, /, *, timeout30) for name, param in sig.parameters.items(): print(name, -, param.kind.name)输出结果为(host, port, /, *, timeout30) host - POSITIONAL_ONLY port - POSITIONAL_ONLY timeout - KEYWORD_ONLY两个标记把参数空间切成了清晰的三个区间我们可以用一个同时包含三种参数的函数一次性观察全貌def f(a, b, /, c, *, d): pass对应的参数分类为参数kind枚举值允许的传参方式a,bPOSITIONAL_ONLY仅限位置cPOSITIONAL_OR_KEYWORD位置或关键字皆可dKEYWORD_ONLY仅限关键字/左侧是位置限定区*右侧是关键字限定区二者之间的c仍保留默认的两种方式皆可语义。理解了这张表组合使用/与*时就不会再对边界感到困惑。术语澄清关键字参数与命名参数原文档在结尾补充了一个值得注意的术语细节在《Python in a Nutshell, 4th Edition》中更严谨的叫法是Named Arguments命名参数而非 Keyword Arguments关键字参数。二者指代的是同一事物——以namevalue形式传递的参数——但在阅读官方文档、第三方库源码或书籍时遇到 keyword-only、keyword-only marker 与 named arguments 混用的情况需要意识到它们是同一概念的不同表述。在 Python 官方文档与类型检查器的报错文案如Unexpected keyword argument中keyword 一词仍是最主流的用法。与仓库中其他 TIL 的呼应*与 dataclass 中的关键字限定*与/并非只能成对出现单独使用其中一个标记就能解决一类常见问题til 仓库中恰好有几篇与本文构成完整知识闭环的笔记只强制关键字、不强制位置如果只想要求部分参数必须以命名方式传入单独使用*即可参见 force-remaining-arguments-to-be-named.md。该文展示了在CliContext.__init__中紧随self放置*从而强制verbose、repo必须显式命名同时也演示了带收集器形式def build_identifier(first, *rest, delimiter/)的用法——此时若不给delimiter命名它会被*rest一并收走导致分隔符失效。dataclass 字段的关键字限定在dataclass中可以用field(kw_onlyTrue)把某个字段标记为仅限关键字参见 configure-other-attributes-of-dataclass-field.md也可以用KW_ONLY哨兵值把其后的所有字段整体划入关键字限定区参见 another-way-to-mark-keyword-only-dataclass-fields.md。这四篇笔记合起来覆盖了普通函数 dataclass两类场景下的参数边界控制而本文的/*组合则是其中约束最严格、语义最完整的一种。实战建议何时该使用严格参数边界综合上面的代码与元数据验证可以总结出几条实用判断标准位置顺序本身承载语义如connect(host, port, /, ...)/可以防止调用方写出connect(host..., port...)这种让代码与直觉顺序脱节的写法也让未来重命名形参时不会悄然破坏外部调用。布尔标志与可选配置如timeout30、verbose这类带默认值的参数放在*右侧强制命名调用处timeout20的语义远优于一个裸数字20这也正是 force-remaining-arguments-to-be-named.md 中作者推荐的做法。需要前后兼容的公开 API/允许你在未来自由调整内部实现而无需担心调用方依赖参数名是标准库和框架维护者常用的兼容性手段。需要注意的是严格边界是一把双刃剑它牺牲了传参灵活性来换取调用方代码的可读性与稳定性。因此它更适合面向外部使用者的公共函数、CLI 入口与配置型构造器而不必应用到每一个内部辅助函数上。小结/与*的组合为 Python 函数提供了最严格的参数边界控制/左侧只能按位置传、*右侧只能按关键字传两者之间则保留默认的混合语义。运行时TypeError会在误用时精确指出违规参数名Pyright 等静态检查器则在编辑器阶段就给出call-arg诊断而inspect.signature的POSITIONAL_ONLY/KEYWORD_ONLY枚举则从元数据层面印证了这一机制。结合仓库中关于*与 dataclass 关键字限定字段的三篇姊妹笔记你可以在普通函数、类构造器与 dataclass 中自如地设计出清晰、稳定、易于维护的参数契约。赞分享文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载相关推荐Python 3函数参数类型完全解析位置、关键字与可变参数Python 3函数参数类型完全解析位置、关键字与可变参数 想要真正掌握Python编程那么函数参数类型绝对是你必须深入理解的核心概念 在Python文档教程AkVirtualCamera终极指南5分钟掌握跨平台虚拟摄像头配置AkVirtualCamera终极指南5分钟掌握跨平台虚拟摄像头配置 想要在视频会议中展示精美演示文稿需要在直播时使用自定义视频源AkVirtualCam终极Jinja函数调用指南掌握位置参数与关键字参数的实用技巧终极Jinja函数调用指南掌握位置参数与关键字参数的实用技巧 Jinja是一款强大的模板引擎广泛应用于Python Web开发中。在Jinja模板中函数调后端上一篇5分钟快速入门DeepXDE科学机器学习与物理信息学习的终极指南下一篇B站视频数据批量采集与分析工具高效使用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表