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年8月20日
Python 版本:
2.0
发布历史:
2000年8月23日

目录

摘要

\x 转义序列(在8位和Unicode字符串中)更改为只消耗紧随其后的两个十六进制数字。本提案认为这是纠正了最初的设计缺陷,有助于在所有类型的字符串中更清晰地表达,更简洁的Unicode方案,更好地与Perl正则表达式兼容,并且对现有代码的风险最小。

语法

在所有非原始字符串中,\x 转义序列的语法变为

\xhh

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

\xhh...

暗示“两个或更多”十六进制数字,但1.5.2编译器也接受一位数字形式,而一个普通的 \x 则“扩展”为自身(即,一个反斜杠后跟字母 x)。目前尚不清楚参考手册是否意图支持1位或0位行为。

语义

在8位非原始字符串中,

\xij

扩展为字符

chr(int(ij, 16))

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

在Unicode字符串中,

\xij

\u00ij

作用相同,即它扩展为Unicode空间初始段中明显的Latin-1字符。

一个 \x 如果后面没有至少两个十六进制数字,则是一个编译时错误,具体来说,在8位字符串中是 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模式下运行,才能收到关于 \x 转义序列后面少于2个十六进制数字的警告——坚持始终要求2个数字显然更具Pythonic风格)。

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

有一些投机取巧的方法可以猜测,但这并非终点。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年8月3日。反馈绝大多数是积极的;没有提出反对意见。

向后兼容性

改变 \x 转义序列的含义确实存在破坏现有代码的风险,尽管尚未发现不兼容的实例。这种风险被认为是最小的。

Tim Peters验证,除了有意挑衅极端情况的标准测试套件部分之外,在Python CVS开发树或他机器上的各种Python包中,都没有发现 \xabcdef... 后跟少于或多于2个十六进制数字的实例。

不太可能有少于2个的,因为参考手册暗示它们是非法的(尽管这一点有争议!)。如果有多于2个的,Guido准备辩称它们本来就有bug <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

最后修改: 2025-02-01 08:55:40 GMT