PEP 679 – 允许在 assert 语句中使用圆括号
- 作者:
- Pablo Galindo Salgado <pablogsal at python.org>
- 讨论列表:
- Discourse 帖子
- 状态:
- 草稿
- 类型:
- 标准跟踪
- 创建:
- 2022年1月7日
- Python 版本:
- 3.12
摘要
本 PEP 提案允许在 assert 语句的双参数形式周围使用圆括号。这将导致解释器重新解释之前会被解释为带有始终为 True 的二元元组的 assert 语句(assert (expression, message)
)的内容,将其视为一个带有主体和失败消息的 assert 语句,等同于去除圆括号后的语句(assert expression, message
)。
动机
在使用包含错误消息的 assert 语句形式时,用户常犯的一个错误是将其用圆括号括起来。不幸的是,这个错误无法被检测到,因为 assert 将始终通过,因为它被解释为一个表达式为二元元组的 assert 语句,而二元元组始终具有真值。
这个错误最常发生在将测试或描述扩展到多行时,因为圆括号是执行此操作的自然方式。
这种情况非常普遍,以至于SyntaxWarning
现在由编译器发出。
此外,语言中的其他一些语句以某种方式允许使用圆括号形式,例如 import
语句(from x import (a,b,c)
)和 del
语句(del (a,b,c)
)。
允许使用圆括号不仅可以消除常见错误,还可以允许用户和自动格式化程序以本文档作者认为更自然的方式将较长的 assert 语句格式化为多行。尽管目前可以将较长的 assert
语句格式化为多行,例如
assert (
very very long
expression
), (
"very very long "
"message"
)
本文档作者认为,带圆括号的形式更清晰,并且与其他语法结构的格式更一致。
assert (
very very long
expression,
"very very long "
"message",
)
此更改最初在[bpo-46167]中进行了讨论和提议。
基本原理
此更改可以在解析器或编译器中实现。我们选择在解析器中实现此更改,因为在编译器中执行此操作将需要重新解释带有二元元组的 assert 语句的 AST
Module(
body=[
Assert(
test=Tuple(
elts=[
Name(id='x', ctx=Load()),
Name(id='y', ctx=Load())],
ctx=Load()))],
type_ignores=[])
作为带有表达式和消息的 assert 语句的 AST。
Module(
body=[
Assert(
test=Name(id='x', ctx=Load()),
msg=Name(id='y', ctx=Load()))],
type_ignores=[])
这种方法的问题在于,第一种形式的 AST 在技术上将是“不正确的”,因为我们已经为带有测试和消息的 assert 语句的 AST(第二种)提供了一种专门的形式。这意味着许多处理 AST 的工具需要了解这种语义变化,这将令人困惑,因为已经存在一种更能表达新含义的正确形式。
规范
本 PEP 提案更改 assert
语句的语法为
| 'assert' '(' expression ',' expression [','] ')' &(NEWLINE | ';')
| 'assert' a=expression [',' expression ]
其中第一行是允许使用圆括号的新 assert 语句形式。需要前瞻,以便 assert (a, b) <= c, "something"
等语句仍然可以正确解析,并防止解析器急切地将元组捕获为完整语句。
可选地,可以添加新的“无效”规则以生成自定义语法错误,以涵盖具有 0、1、3 或更多元素的元组。
向后兼容性
此更改在技术上不向后兼容,因为解析 assert (x,y)
目前被解释为一个以 2 元组作为主体的 assert 语句,而在此更改之后,它将被解释为 assert x,y
。
另一方面,这种类型的 assert 语句始终通过,因此它们实际上在用户代码中没有任何作用。本文档作者认为这种向后不兼容性是有益的,因为它将突出显示用户代码中的这些情况,而之前它们将未被注意到(假设这些情况仍然存在,因为用户忽略了语法警告)。
安全影响
此更改没有安全影响。
如何教授
新的 assert
语句形式将作为语言标准的一部分进行记录。
在向用户教授包含错误消息的 assert
语句形式时,现在可以注意到添加圆括号也能按预期工作,这允许将语句拆分为多行。
参考实现
包含此更改的提议草案 PR 存在于[GH-30247]中。
参考文献
版权
本文档置于公共领域或根据 CC0-1.0-Universal 许可证,以两者中较宽松者为准。
来源:https://github.com/python/peps/blob/main/peps/pep-0679.rst