尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Ruff ty 类型检查器规则解析:invalid-legacy-positional-parameter 与 Python 位置参数的两代约定
Ruff ty 类型检查器规则解析invalid-legacy-positional-parameter 与 Python 位置参数的两代约定【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff本篇技术指南围绕 Ruff 仓库中 ty 类型检查器位于crates/ty_python_semantic等 crate入口参见 crates/ty/README.md的invalid-legacy-positional-parameter规则展开说明它为何检测以__双下划线开头却无法被类型检查器识别为仅限位置positional-only参数的写法并从 PEP 484 遗留约定、PEP 570 正式语法到该规则的源码实现层层拆解。读完本文你将理解这条 lint 的触发条件与边界掌握修正旧式位置参数写法的两种方案并能定位其检查逻辑、AST 判定函数与签名构建流程的源码位置在实际项目中准确复现与规避该诊断。规则定位它在检查什么该规则的官方文档位于 crates/ty_python_semantic/resources/lint_docs/invalid-legacy-positional-parameter.md语义描述为检查那些试图使用遗留约定legacy convention声明某个参数为 positional-only但写法并不正确the parameter appears right after a normal positional-or-keyword parameter的情况。围绕这条规则有两代仅限位置参数的规范需要厘清PEP 484 遗留约定legacy conventionPEP 484 规定对于名称以__开头且不以__结尾的参数类型检查器应当将其视为 positional-only。这套约定只对静态类型检查器生效Python 运行时并不会因此限制调用方式。PEP 570 正式语法Python 3.8在函数参数列表中使用/分隔符显式声明其左侧的所有参数为 positional-only。该语法自 Python 3.8 起可用使 PEP 484 的__命名约定变得过时。正因如此仍有一些代码库为了兼容 Python 3.7 及更早版本而继续沿用__命名约定——这正是invalid-legacy-positional-parameter规则存在的意义它不是要禁用遗留约定而是要拦截错误地使用遗留约定的情况。为什么这种写法是错的按 PEP 484 的约定类型检查器只会把处于参数列表最前面一段连续位置即所有 positional-or-keyword 参数之前的__前缀参数视为 positional-only。一旦某个__前缀参数出现在一个普通的 positional-or-keyword 参数之后类型检查器就不会再把它当作 positional-only而只会当它是一个以__开头的普通参数。这往往与代码作者的预期相悖——作者以为已经借命名约定了禁用关键字传参实际并没有。触发示例与两种修复方案规则文档给出了最典型的错误样例# __y 不会被类型检查器视为 positional-only def f(x, __y): # error pass由于x是一个 positional-or-keyword 参数且排在__y之前类型检查器无法把__y归入前导 positional-only 段于是触发本规则。修正方法有两条路径取决于你愿意支持的最低 Python 版本方案一让所有 positional-only 参数连续排在最前兼容 Python 3.7def f(__x, __y): # 需要兼容 Python 3.7 时使用 pass把x也改名为__x使__前缀参数形成从参数列表开头连续的一段满足 PEP 484 遗留约定对前导位置的要求。方案二升级到 Python 3.8 的显式/语法def f(x, y, /): # Python 3.8 语法 pass/之前的x、y均被显式声明为 positional-only。这条路径不依赖任何命名技巧语义最清晰也是现代代码的首选。实践中的边界情况从源码实现可以确认该规则还有几个值得注意的边界已使用 PEP 570 语法时不再做遗留约定检查检查函数会先判断 AST 参数列表中是否已存在/声明的 positional-only 参数posonlyargs若存在则整个跳过本次检查见下文源码解析避免新旧语法混用场景下产生噪声。真正的 dunder 名称不会被误伤规则命中的条件是名称以__开头且不以__结尾因此__init__、__call__这类 dunder 方法参数不会被当作遗留约定的使用者。方法隐式收参self/cls会先占位在方法签名构建时隐式收参会先被排入 positional-only 段见下文签名构建逻辑其后紧跟的__前缀参数仍可被正确识别。源码级解读规则如何落地下面沿规则声明 → 函数入口 → 判定逻辑 → AST 判定方法 → 签名构建这条链梳理实现所有路径均以当前仓库为准。规则声明默认级别与稳定版本规则通过declare_lint!宏声明于 crates/ty_python_semantic/src/types/diagnostic.rssummarydetects incorrect usage of the legacy convention for specifying positional-only parametersdefault_levelWarn默认警告级不作为错误阻断statusstable(0.0.15)即自 0.0.15 版本起稳定可用同一规则也登记于 crates/ty/docs/rules.md 的规则总表中该 lint 在运行时通过registry.register_lint(INVALID_LEGACY_POSITIONAL_PARAMETER)注册见 diagnostic.rs。检查入口与触发点函数定义的各类诊断在check_function_definition中统一调度其中就包含对遗留约定的专项检查调用见 post_inference/function.rs。需要说明的是进入该函数之前带有不进行类型检查类装饰器no_type_check的函数定义会被提前返回从而整体跳过包括本规则在内的一批函数级诊断见 function.rs。核心判定函数判定主体为check_legacy_positional_only_convention位于 post_inference/function.rs。其逻辑要点如下前置过滤若ast_parameters.posonlyargs非空即函数已显式使用 PEP 570/语法直接返回不做遗留约定检查。配对遍历将 AST 参数节点与解析后的签名参数signature.parameters()按位置一一配对逐一跳过变长参数*args等。双阶段识别对某个__前缀参数而言合法的遗留约定用法会在签名构建阶段被识别并标记为 positional-only从而在这里被continue跳过只有那些没有被识别为 positional-only、却仍然以__开头即uses_pep_484_positional_only_convention()返回 true的参数才会走到报告逻辑——这正好印证了文档所述排在 positional-or-keyword 参数之后的__参数是无效遗留约定。诊断信息命中时报告主注解消息Parameter name begins with__but will not be treated as positional-only附加说明infoA parameter can only be positional-only if it precedes all positional-or-keyword parameters若存在更早出现的普通参数则在其名称上追加辅助注解Prior parameter here was positional-or-keyword帮助用户一眼定位破坏前导连续性的那个参数。同时函数维护previous_non_positional_only游标遇到第一个非 positional-only 参数后就不再更新用于给后续所有无效__参数提供参照物注解。AST 层的判定方法是否是 PEP 484 遗留约定的写法这一判断被封装在 AST 节点的工具方法中见 crates/ruff_python_ast/src/nodes.rs/// Return true if the parameter name uses the pre-PEP-570 convention /// (specified in PEP 484) to indicate to a type checker that it should be treated /// as positional-only. pub fn uses_pep_484_positional_only_convention(self) - bool { let name self.name(); name.starts_with(__) !name.ends_with(__) }即__foo、__bar命中__init__、__self__这类 dunder 因为以__结尾而被排除。签名构建为何前导连续才有效若要真正理解为什么__y跟在x后面就失效需要看签名构建阶段的处理见 crates/ty_python_semantic/src/types/signatures.rs首先收集 PEP 570 显式声明的 positional-only 参数posonlyargs仅当显式 positional-only 参数为空时才回退去识别 PEP 484 遗留约定若函数存在隐式位置收参如方法中的self/cls对应has_implicitly_positional_first_parameter先把它作为 positional-only 放入随后用peeking_take_while从头连续地吞下所有uses_pep_484_positional_only_convention()为真的参数并把它们标记为ParameterKind::PositionalOnlytake_while意味着一旦遇到第一个不符合约定的参数后续即使再出现__前缀参数也不会再被吞入它们将落入普通的PositionalOrKeyword段——于是排在中途的__参数就必然成为invalid-legacy-positional-parameter的靶子。这条实现链条清晰印证了规则文档的核心结论legacy 约定下一个参数要成为 positional-only必须位于所有 positional-or-keyword 参数之前。如何运行与验证该类型检查器在仓库内以独立的tybin 形式提供可通过 Cargo 直接运行见 crates/ty/CONTRIBUTING.mdcargo run --bin ty -- check /path/to/project/ty check会检查项目中的类型错误由于invalid-legacy-positional-parameter的默认级别是warn在不额外配置时它就会出现在输出中可用于直观验证上文的触发与修复示例。想要快速做一次验证可以建一个临时文件写入def f(x, __y): pass再对其执行ty check。与其他规则的关联在同一个 lint 文档目录中还存在语义互补的兄弟规则 positional-only-parameter-as-kwarg它检测的是调用侧把 positional-only 参数按关键字传入的误用而invalid-legacy-positional-parameter关注的是定义侧用遗留命名约定声明 positional-only 却声明失败的问题。二者分别从函数定义与函数调用两个方向守护 positional-only 语义的一致性与正确性。小结invalid-legacy-positional-parameter是一条面向历史兼容代码的类型检查 lint它允许你在仍支持 Python ≤ 3.7 的前提下沿用 PEP 484 的__命名约定但会坚决拦截试图用遗留约定声明、却因位置靠后而实际无效的参数。修复时优先推荐迁移到 Python 3.8 的/显式语法若必须保持旧运行时兼容则将__前缀参数整理到参数列表最前的连续区间即可。要深入掌握这条规则建议依次阅读 规则文档、规则声明、核心判定逻辑 与 签名构建逻辑四者合起来即是约定是什么、为什么错、何时报告、底层如何判定的完整答案。【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

同花顺日线文件二进制解析:从零还原K线数据到DataFrame

同花顺日线文件二进制解析:从零还原K线数据到DataFrame

简介:面向股票数据分析与Python开发者,这份资源演示了如何用约20行代码解析同花顺日线.day二进制文件。.day文件是存储股票历史交易数据的专有格式,包含日期、开盘价、收盘价、最高价、最低价、成交量、成交额等关键信息;脚本从二…

📅 2026/9/9 21:08:12
SpringBoot+Vue校园资料分享平台:权限控制与分片上传实践

SpringBoot+Vue校园资料分享平台:权限控制与分片上传实践

校园里找资料有多痛苦,估计每个经历过期末的人都懂:课程PPT散落在十几个群聊里,学长学姐的笔记存在个人网盘链接且经常失效,想找一份往年试卷得靠人品。做这个前后端分离的校园资料分享平台,初衷就是把这堆烂摊子收拢成…

📅 2026/9/9 21:08:12
GD32烧录指南:GD LINK Programmer配置、操作与故障排查

GD32烧录指南:GD LINK Programmer配置、操作与故障排查

简介:GD LINK Programmer是专为国产GD32系列微控制器打造的烧录工具,面向嵌入式开发者与硬件工程师,解决程序下载、固件更新及在线调试等环节的痛点。工具兼容GD32全系列芯片,覆盖Cortex-M3/M4/F4内核,支持ISP与IAP编程…

📅 2026/9/9 21:03:11
MORE NEWS

更多资讯

📰

暗物质探测器校准算法:从波形提取到能量刻度的技术全解

1. 校准这件事,为什么在暗物质实验里难上加难我做暗物质探测器数据处理有些年头了,每次有新人入组,问的第一个问题十有八九是:“不就是拿标准源打一遍、画个刻度曲线吗?有那么复杂?”等到他亲手跑完一轮完整…

📰

.P3D三维模型资产导入全流程:从格式识别到引擎集成实践指南

这次我们来看一个特殊类型的数字资产项目:标题为“-Trio infected astro titan-”的 .P3D 三维模型文件。如果你在游戏模组社区、3D 资源站或角色渲染工作流里看到这类命名,大概率遇到的是一个“主题型 3D 模型资产包”:文件名暗示了内容主题…

📰

OpenCore Legacy Patcher 实操指南:老 Mac 升级 Big Sur 到 Sequoia 的完整路径

OpenCore Legacy Patcher 实操指南:老 Mac 升级 Big Sur 到 Sequoia 的完整路径 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 把一台 2013 年的…

📰

EC20 4G模块TCP透传模式配置全流程:从AT指令到串口数据桥接实战

简介:面向STM32F4系列开发者的EC20模块TCP透传模式通信工程示例,解决微控制器通过AT指令建立套接字连接并透明收发数据的常见需求。资源适合有一定嵌入式基础、正在调试无线通信模块的开发者,也适合作为物联网终端联网功能的学习参考。压缩包…

📰

智能制造解决方案:如何系统提升企业生产效率

一、制造业的效率焦虑:问题在哪里很多制造企业谈到“提升效率”时,第一反应是上自动化设备、改造产线,或者要求员工加快动作。但产线跑得再快,如果数据采集靠手工抄表、生产排程靠经验拍板、质量异常靠事后抽检、设备故障靠坏了再…

📰

书霸AI问卷设计实操指南

书霸AI官网:www.shubaai.com做论文问卷时,很多人并不是不会提问,而是不知道如何把研究问题转化为一份结构合理、便于分析的问卷。题目太少,难以支撑研究结论;题目太多,受访者容易失去耐心;选项设…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬