PEP 215 – 字符串插值
- 作者:
- Ka-Ping Yee <ping at zesty.ca>
- 状态:
- 已取代
- 类型:
- 标准跟踪
- 创建日期:
- 2000年7月24日
- Python 版本:
- 2.1
- 发布历史:
- 取代者:
- 292
摘要
本文档提出了 Python 的字符串插值功能,以实现更简单的字符串格式化。建议的语法更改是引入一个“$”前缀,它会触发字符串内“$”字符的特殊解释,其方式类似于 Unix shell、awk、Perl 或 Tcl 中发现的变量插值。
版权
本文档属于公共领域。
规范
字符串可以带有一个“$”前缀,该前缀位于开头的单引号或双引号(或三引号)之前,以及任何其他字符串前缀(“r”或“u”)之前。此类字符串在其内容中的反斜杠转义符被正常解释后,会进行插值处理。处理发生在字符串被推入值堆栈之前,每次字符串被推入时。简而言之,Python 的行为就像“$”是对字符串应用的一元运算符。执行的操作如下:
字符串从头到尾扫描“$”字符(8 位字符串中的 \x24 或 Unicode 字符串中的 \u0024)。如果不存在“$”字符,则返回未更改的字符串。
字符串中找到的任何“$”,后跟以下两种表达式之一,都将替换为在当前命名空间中计算的表达式值。如果包含字符串是 8 位字符串,则使用 str() 转换值;如果是 Unicode 字符串,则使用 unicode() 转换值。
- 一个 Python 标识符,可选地后跟任意数量的尾部,其中尾部由以下组成:- 一个点和一个标识符,- 一个用方括号括起来的表达式,或 - 一个用括号括起来的参数列表(这正是 Python 语法中由“
NAME trailer*”表达的模式,使用Grammar/Grammar中的定义。) - 任何用大括号括起来的完整 Python 表达式。
两个美元符号(“$$”)替换为一个“$”。
示例
这是一个交互式会话示例,展示了此功能的预期行为。
>>> a, b = 5, 6
>>> print $'a = $a, b = $b'
a = 5, b = 6
>>> $u'uni${a}ode'
u'uni5ode'
>>> print $'\$a'
5
>>> print $r'\$a'
\5
>>> print $'$$$a.$b'
$5.6
>>> print $'a + b = ${a + b}'
a + b = 11
>>> import sys
>>> print $'References to $a: $sys.getrefcount(a)'
References to 5: 15
>>> print $"sys = $sys, sys = $sys.modules['sys']"
sys = <module 'sys' (built-in)>, sys = <module 'sys' (built-in)>
>>> print $'BDFL = $sys.copyright.split()[4].upper()'
BDFL = GUIDO
讨论
选择“$”作为字符串中的插值字符是为了熟悉,因为它已在许多其他语言和上下文中用于此目的。
然后,自然地选择“$”作为前缀,因为它是一个插值字符的助记符。
允许尾部使这种插值机制比大多数其他语言中可用的插值功能更强大,同时要插值的表达式仍然清晰可见且没有大括号。
“$”像运算符一样工作,可以作为运算符实现,但这会阻止编译时优化并带来安全问题。因此,它只允许作为字符串前缀。
安全问题
“$”具有求值的能力,但只能对字面量进行求值。如本文所述(作为字符串前缀而不是运算符),它不会引入新的安全问题,因为要计算的表达式必须以字面量形式存在于代码中。
实施
[1] 处的 Itpl 模块提供了此功能的原型。它使用 tokenize 模块查找要插值表达式的末尾,然后在每次需要值时对表达式调用 eval()。在原型中,每次评估时都会再次解析和编译表达式。
作为一种优化,插值字符串可以直接编译成相应的字节码;也就是说,
$'a = $a, b = $b'
可以像表达式一样编译
('a = ' + str(a) + ', b = ' + str(b))
这样它只需要编译一次。
参考资料
来源: https://github.com/python/peps/blob/main/peps/pep-0215.rst
上次修改: 2024-04-14 13:35:25 GMT