Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 223 – 更改 \x 转义符的含义

作者:
Tim Peters <tim.peters at gmail.com>
状态:
最终
类型:
标准跟踪
创建:
2000-08-20
Python 版本:
2.0
历史记录:
2000-08-23

目录

摘要

更改 \x 转义符(在 8 位和 Unicode 字符串中)以精确地使用其后的两个十六进制数字。该提案将此视为纠正原始设计缺陷,从而在所有字符串类型中实现更清晰的表达,更清晰的 Unicode 故事,与 Perl 正则表达式更好的兼容性,并且对现有代码的风险最小。

语法

所有类型非原始字符串中 \x 转义符的语法变为

\xhh

其中 h 是十六进制数字(0-9,a-f,A-F)。1.5.2 中的精确语法在参考手册中没有明确说明;它说

\xhh...

这意味着“两个或多个”十六进制数字,但 1.5.2 编译器也接受一位数字形式,并且一个简单的 \x 被“扩展”为自身(即反斜杠后跟字母 x)。目前尚不清楚参考手册是否打算使用一位数字或零位数字行为。

语义

在 8 位非原始字符串中,

\xij

扩展为字符

chr(int(ij, 16))

请注意,这与 1.6 及之前版本相同。

在 Unicode 字符串中,

\xij

与以下相同

\u00ij

即它扩展为 Unicode 空间初始段中的明显拉丁-1 字符。

在 8 位字符串中,一个后面没有至少两个十六进制数字的 \x 是编译时错误,具体来说是 ValueError,在 Unicode 字符串中是 UnicodeErrorValueError 的子类)。请注意,如果 \x 后面跟着两个以上的十六进制数字,则只“使用”前两个。在 1.6 及之前版本中,除了最后两个以外,所有其他数字都被静默忽略。

示例

在 1.5.2 中

>>> "\x123465"  # same as "\x65"
'e'
>>> "\x65"
'e'
>>> "\x1"
'\001'
>>> "\x\x"
'\\x\\x'
>>>

在 2.0 中

>>> "\x123465" # \x12 -> \022, "3456" left alone
'\0223456'
>>> "\x65"
'e'
>>> "\x1"
[ValueError is raised]
>>> "\x\x"
[ValueError is raised]
>>>

历史和理由

\x 转义符是在 C 中引入的一种方法,用于指定可变宽度字符编码。这些编码究竟是什么,以及它们需要多少个十六进制数字,由每个实现决定。该语言只是简单地说明 \x“使用”所有后面的十六进制数字,并将含义留给每个实现决定。因此,实际上,C 中的 \x 是一个标准钩子,用于提供平台定义的行为。

由于 Python 明确地以平台无关性为目标,因此 Python 中的 \x 转义符(直至 1.6 版本)在所有平台上都被视为相同:除了最后两个十六进制数字被静默忽略。因此,Python 中 \x 转义符的唯一实际用途是使用十六进制表示法指定单个字节。

Larry Wall 似乎意识到这是平台无关语言中 \x 转义符的唯一真正用途,因为 Python 2.0 的提议规则实际上是 Perl 从一开始就采用的方法(尽管你需要在 Perl -w 模式下运行才能获得有关后面不到 2 个十六进制数字的 \x 转义符的警告 - 始终坚持 2 个明显更 Pythonic 的方法)。

当 Unicode 字符串被引入到 Python 时,\x 被泛化,以便在 Unicode 字符串中忽略除最后四个十六进制数字以外的所有数字。这给新的正则表达式引擎带来了技术困难:SRE 非常努力地以直观的方式允许混合 8 位和 Unicode 模式和字符串,它不再有任何方法来猜测例如 r"\x123456" 作为模式的含义:它是在要求匹配 8 位字符 \x56 还是 Unicode 字符 \u3456

有一些 hacky 的方法可以猜测,但这并没有结束。ISO C99 标准还引入了 8 位数字 \U12345678 转义符来覆盖整个 ISO 10646 字符空间,并且 Python 2 也希望从一开始就支持这一点。那么 \x 转义符应该意味着什么?它们会忽略除最后个十六进制数字以外的所有数字吗?如果在 Unicode 字符串中少于 8 个,则会忽略除最后 4 个以外的所有数字?如果少于 4 个,则会忽略除最后 2 个以外的所有数字?

这种情况每分钟都变得更加混乱,该提议通过使 \x 更简单而不是更复杂来解开这个戈尔迪之结。请注意,对 Unicode 字符串中 \xijkl 的 4 位数字泛化也是多余的,因为它与 Unicode 字符串中的 \uijkl 具有完全相同的含义。用一种显而易见的方法来通过十六进制表示法指定 Unicode 字符,这更符合 Pythonic 的风格。

开发和讨论

该提议是在 Guido van Rossum、Fredrik Lundh 和 Tim Peters 之间通过电子邮件协商完成的。随后在 Python-Dev 上以“Go x yourself”为主题进行了解释和讨论 [1],从 2000-08-03 开始。响应极其正面;没有提出异议。

向后兼容性

更改 \x 转义符的含义确实存在破坏现有代码的风险,尽管尚未发现任何不兼容的实例。据信该风险极小。

Tim Peters 验证了,除了故意激发最终情况的标准测试套件的一部分外,在 Python CVS 开发树中或他机器上各种 Python 包中,都没有 \xabcdef... 的实例,这些实例后面跟着少于或多于 2 个十六进制数字。

不太可能出现少于 2 个的情况,因为参考手册暗示它们是非法的(尽管这是可以争论的!)。如果有任何实例后面跟着超过 2 个,Guido 准备争辩说无论如何它们都是有错误的 <0.9 wink>。

Guido 报告说,O'Reilly 的 Python 书籍已经记录了 Python 以提议的方式工作,这可能是由于它们的 Perl 编辑传统(如上所述,Perl 从一开始就以(非常接近)提议的方式工作)。

Finn Bock 报告说,JPython 今天对 \x 转义符的处理是不可预测的。该提议给出了一个清晰的含义,可以在所有 Python 实现中一致且轻松地实现。

对其他工具的影响

据信没有。可能出现损坏的候选者主要是解析工具,但作者不知道任何对 Python 字符串的内部结构感到担心的工具,除了“当出现反斜杠时,吞掉下一个字符”这一近似值。Tim Peters 检查了 python-mode.el、标准 tokenize.pypyclbr.py 以及 IDLE 语法着色子系统,并且相信不需要更改任何一个。像 tabnanny.pycheckappend.py 这样的工具从 tokenize.py 继承了它们的免疫力。

参考实现

代码更改非常简单,因此不会产生单独的补丁。Fredrik Lundh 正在编写代码,他是该领域的专家,他将在 2.0b1 发布之前简单地检查这些更改。

BDFL 声明

是的,ValueError,而不是 SyntaxError。“字面解释问题通常会引发‘运行时’异常,而不是语法错误。”

参考资料


来源:https://github.com/python/peps/blob/main/peps/pep-0223.rst

最后修改:2023-09-09 17:39:29 GMT