PEP 536 – 字面量字符串插值最终语法
- 作者:
- Philipp Angerer <phil.angerer at gmail.com>
- 状态:
- 已撤回
- 类型:
- 标准跟踪
- 创建:
- 2016-12-11
- Python 版本:
- 3.7
- 历史记录:
- 2016-08-18, 2016-12-23, 2019-03-15
- 决议:
- 讨论信息
摘要
PEP 498 引入了字面量字符串插值(或“f-字符串”)。但是,这些字面量的表达式部分受到某些限制。本 PEP 提出了一种正式的语法,取消了这些限制,将“f-字符串”提升为“f-表达式”或 f-字面量。
PEP 撤回
术语
本文将把现有语法称为“f-字符串”,把提议的语法称为“f-字面量”。
此外,它将把 f-字面量/f-字符串中用 {}
分隔的表达式称为“表达式部分”,并将周围的静态字符串内容称为“字符串部分”。
动机
CPython 中 f-字符串的当前实现依赖于现有的字符串解析机制及其标记的后处理。这导致了对 f-字符串中可用的可能表达式的若干限制。
- 无法在表达式部分中使用分隔 f-字符串的引号字符。
>>> f'Magic wand: { bag['wand'] }' ^ SyntaxError: invalid syntax
- 之前考虑过的一种解决方法会导致执行代码中的转义序列,并且在 f-字符串中是被禁止的。
>>> f'Magic wand { bag[\'wand\'] } string' SyntaxError: f-string expression portion cannot include a backslash
- 即使在多行 f-字符串中也禁止使用注释。
>>> f'''A complex trick: { ... bag['bag'] # recursive bags! ... }''' SyntaxError: f-string expression part cannot include '#'
- 表达式部分需要将
':'
和'!'
括在括号中。>>> f'Useless use of lambdas: { lambda x: x*2 }' SyntaxError: unexpected EOF while parsing
这些限制从语言用户的角度来看没有任何意义,可以通过赋予 f-字面量一个没有异常的常规语法并使用专用的解析代码来实现它来消除。
基本原理
除非用户熟悉 f-字面量的实现细节,否则 动机 中提到的限制并不明显且违反直觉。
如前所述,PEP 498 的早期版本允许在 f-字符串中的任何位置使用转义序列,包括作为编码分隔表达式部分的括号和在其代码中的方法。它们将在解析代码之前展开,这将产生几个重要的影响。
#. 人类读者将无法清楚地分辨哪些部分是表达式,哪些部分是字符串。这是“混淆/卑鄙的 Python 挑战”的绝佳素材。#. 语法高亮器擅长解析嵌套语法,但不擅长识别转义序列。ECMAScript 2016(JavaScript)在其标识符中允许转义序列 [1],并且作者知道没有语法高亮器能够正确突出显示使用此功能的代码。
因此,使用或不使用语法高亮器,表达式部分都更难识别。使用新语法,可以轻松扩展语法高亮器以正确解析和显示 f-字面量。
f'Magic wand: {bag['wand']:^10}'
突出显示可能包含转义序列的表达式部分意味着要创建完整表达式语法的全部规则的修改副本,以考虑关键字、分隔符和所有其他语言语法中转义序列的可能性。这样的重复将产生一个转义深度级别,并且必须针对递归 f-字面量中的更深层转义重复。这是因为作者所知的没有语法高亮引擎支持在将规则应用于特定上下文之前展开转义序列。但是,嵌套上下文是所有语法高亮引擎的标准功能。
熟悉度也起着作用:在使用表达式而不是仅仅使用变量名称的字符串插值方法的每一种其他语言中,都提供了表达式无需展开转义序列的任意嵌套。 [2]
规范
PEP 498 将 f-字符串指定如下,但对其进行了限制。
f ' <text> { <expression> <optional !s, !r, or !a> <optional : format specifier> } <text> ... '
PEP 中提到的所有限制都从 f-字面量中取消,如下所述。
- 表达式部分现在可以包含用与分隔 f-字面量相同的引号字符分隔的字符串。
- 反斜杠现在可以出现在表达式中,就像在 Python 代码中的任何其他位置一样。对于嵌套在 f-字面量中的字符串,在评估最内层字符串时会展开转义序列。
- 注释(使用
'#'
字符)仅在多行 f-字面量中可用,因为注释以行尾终止(这使得关闭单行 f-字面量变得不可能)。 - 表达式部分可以在语法上有效的位置包含
':'
或'!'
。第一个不属于表达式的':'
或'!'
后面必须跟一个有效的强制转换或格式说明符。
PEP 498 没有明确提及的另一个剩余限制是表达式部分中的换行符。由于用单个 '
或 "
字符分隔的字符串预计为单行,因此单行字符串的表达式部分中换行符仍然是非法的。
注意
取消这些限制就足够了吗?或者我们应该指定一个更完整的语法?
向后兼容性
f-字面量与 f-字符串完全向后兼容,并扩展了被认为是合法的语法。
参考实现
待定
参考文献
版权
本文档已进入公有领域。
来源: https://github.com/python/peps/blob/main/peps/pep-0536.rst
上次修改: 2023-10-26 09:35:14 GMT