Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 增强提案

PEP 3131 – 支持非 ASCII 标识符

作者:
Martin von Löwis <martin at v.loewis.de>
状态:
最终
类型:
标准跟踪
创建:
2007 年 5 月 1 日
Python 版本:
3.0
历史记录:


目录

摘要

此 PEP 建议在 Python 标识符中支持非 ASCII 字母(如带重音符号的字符、西里尔字母、希腊字母、汉字等)。

基本原理

世界各地有许多人编写 Python 代码,他们不熟悉英语,甚至对拉丁字母系统也不熟悉。这些开发人员通常希望使用他们母语来定义类和函数,而不必想出他们想要命名的概念的(通常不正确的)英语翻译。通过使用母语标识符,代码清晰度和代码在该语言使用者之间的可维护性得到了提高。

对于某些语言,存在常见的转写系统(特别是针对基于拉丁字母的书写系统)。对于其他语言,用户在使用拉丁字母来写他们的母语单词方面存在更大的困难。

常见反对意见

人们经常对类似于此提议的提议提出一些反对意见。

人们声称,如果要使用一个库,他们将无法使用它,因为他们无法在键盘上输入他们需要的字符。但是,由库的设计者决定使用库的各种约束:人们可能无法使用库,因为他们无法获得源代码的物理访问权限(因为没有发布),或者因为许可禁止使用,或者因为文档是用他们无法理解的语言编写的。希望使库广泛可用的开发人员需要做出一些明确的选择(例如发布、许可、文档语言和标识符语言)。这些决定应该始终由作者做出,而不是由语言设计人员做出。

特别是,希望获得广泛使用的项目可能希望建立一个策略,即所有标识符、注释和文档都用英语编写(参见 GNU 编码风格指南,了解此类策略的示例)。将语言限制为仅 ASCII 标识符不会强制注释和文档为英语,或标识符实际上为英语单词,因此无论如何都需要额外的策略。

语言更改规范

Python 中标识符的语法将基于 Unicode 标准附录 UAX-31 [1],并根据以下定义进行扩展和更改。

在 ASCII 范围内(U+0001..U+007F),标识符的有效字符与 Python 2.5 中相同。此规范仅从 ASCII 范围之外引入其他字符。对于其他字符,分类使用 unicodedata 模块中包含的 Unicode 字符数据库版本。

标识符语法为 <XID_Start> <XID_Continue>*

可以从 Unicode 数据(在编写此 PEP 时为 4.1)中使用的 Python 的 DerivedCoreProperties 文件中找到哪些字符具有 XID_Start 或 XID_Continue 属性的确切规范,请参阅 [6]。为了参考,这些集合的构造规则如下给出。XID_* 属性是从 ID_Start/ID_Continue 派生的,而 ID_Start/ID_Continue 本身又是派生的。

ID_Start 定义为所有具有以下一般类别之一的字符:大写字母(Lu)、小写字母(Ll)、首字母大写字母(Lt)、修饰字母(Lm)、其他字母(Lo)、字母数字(Nl)、下划线,以及带有 Other_ID_Start 属性的字符。XID_Start 然后在规范化下关闭此集合,方法是删除所有其 NFKC 规范化不再是 ID_Start ID_Continue* 形式的字符。

ID_Continue 定义为 ID_Start 中的所有字符,再加上非间距标记(Mn)、间距组合标记(Mc)、十进制数字(Nd)、连接标点符号(Pc),以及带有 Other_ID_Continue 属性的字符。同样,XID_Continue 在 NFKC 规范化下关闭此集合;它还添加了 U+00B7 来支持加泰罗尼亚语。

所有标识符在解析时都会转换为规范形式 NFKC;标识符的比较基于 NFKC。

可以在 http://www.dcl.hpi.uni-potsdam.de/home/loewis/table-3131.html 处找到一个非规范性 HTML 文件,该文件列出了 Unicode 4.1 的所有有效标识符字符。

策略规范

作为对 Python 编码风格的补充,规定以下策略:Python 标准库中的所有标识符 MUST 使用仅 ASCII 的标识符,并且 SHOULD 在可行的情况下使用英语单词(在许多情况下,使用不是英语的缩写和术语)。此外,字符串字面量和注释也必须是 ASCII。唯一的例外是 (a) 测试非 ASCII 功能的测试用例,以及 (b) 作者姓名。姓名不是基于拉丁字母的作者 MUST 提供其姓名的拉丁语转写。

作为一种选择,此规范可以应用于 Python 2.x。在这种情况下,仅 ASCII 的标识符将继续在名称空间字典中以字节字符串对象的表示形式表示;具有非 ASCII 字符的标识符将以 Unicode 字符串表示。

实施

解析器需要进行以下更改

  1. 如果在源代码的 UTF-8 表示形式中发现非 ASCII 字符,则会进行正向扫描以查找第一个 ASCII 非标识符字符(例如空格或标点符号字符)
  2. 整个 UTF-8 字符串被传递给一个函数,以将字符串规范化为 NFKC,然后验证它是否遵循标识符语法。不会对纯 ASCII 标识符进行此类调用,它们将继续以今天的形式解析。Unicode 数据库必须开始包含 Other_ID_{Start|Continue} 属性。
  3. 如果此规范针对 2.x 实施,则反射库(如 pydoc)必须经过验证,以确保在 __dict__ 槽位中作为键出现 Unicode 字符串时继续工作。

开放问题

John Nagle 建议考虑 Unicode 技术标准 #39,[2],该标准讨论了 Unicode 标识符的安全机制。尚不清楚这如何精确地应用于此 PEP;可能的后果是

  • 警告在 xidmodifications.txt 中列出的“受限”字符
  • 警告使用混合脚本的标识符
  • 以某种方式执行混淆检测

在后两种方法中,尚不清楚算法应如何精确地工作。对于混合脚本,可能应该允许某些类型的混合 - 这些是第 5 节中提到的“通用”和“继承”脚本吗?对于混淆检测,似乎需要两个标识符才能将它们进行比较以确定是否混淆 - 是否可以以某种方式仅将其应用于单个标识符,并发出警告?

在后续讨论中,事实证明 John Nagle 实际上是想建议 UTR#36,级别“高度限制性”,[3]

几个人建议允许和忽略格式控制字符(一般类别 Cf),就像在 Java、JavaScript 和 C# 中一样。尚不清楚这是否会改善情况(对于 RTL 语言来说,它可能会改善);如果需要,这些可以稍后添加。

有些人希望在运行时看到一个选项来选择对此 PEP 的支持;关于此选项应该是什么以及它的默认值应该是什么,人们的意见不一致。Guido van Rossum 在 [5] 中评论说,传递给解释器的全局标志不可接受,因为它将应用于所有模块。

讨论

Ka-Ping Yee 在 [4] 中总结了讨论和进一步反对意见,如下所示

  1. 是否应该允许标识符包含任何 Unicode 字母?

    允许非 ASCII 标识符的缺点

    1. Python 将失去以可靠方式往返于屏幕或纸上的人类可读显示的能力。
    2. Python 将变得容易受到新型安全漏洞的攻击;代码和提交的补丁将难以检查。
    3. 人类将无法再验证 Python 语法。
    4. Unicode 非常年轻;其问题尚未得到很好的理解和解决;工具支持薄弱。
    5. 使用非 ASCII 标识符的语言使用不同的字符集和规范化方案;PEP 3131 的选择并不明显。
    6. 当数字或运算符在附近时,Unicode 双向算法会产生对 RTL 文本极具迷惑性的显示顺序。
  2. 默认行为应该只接受 ASCII 标识符,还是应该接受包含非 ASCII 字符的标识符?

    默认情况下仅限 ASCII 的论据

    1. 默认情况下使用非 ASCII 标识符会使常见的做法/假设变得微妙地/无意中错误;很少有错误比明显错误更糟糕。
    2. 最好发出警告,而不是在遇到可能意外的情况时静默失败。
    3. 当前的所有用法都是仅限 ASCII 的;未来绝大多数用法都将是仅限 ASCII 的。
    1. 采用 Unicode 的是地方性的,而不是 ASCII 支持者。
    2. Python 应该出于与它审计制表符-空格一致性相同的原因来审计仅限 ASCII 的标识符
    3. 渐进式更改更安全。
    4. 仅限 ASCII 的默认值有利于开源开发和源代码共享。
    5. 现有项目无需浪费任何脑力来担心 Unicode 标识符的影响。
  3. 非 ASCII 标识符应该可选吗?

    支持标志的各种声音(尽管人们一直在争论哪一个应该是默认值,但似乎没有人说不应该有关闭开关)

  4. 是否应该配置标识符字符集?

    各种声音提出和支持可选择的字符集,以便用户可以从使用自己的语言中获得所有好处,而不会遇到混淆/不熟悉的字符的缺点

  5. 应该允许哪些标识符字符?
    1. 如何处理双向格式控制字符?
    2. 其他 ID_Continue 字符怎么办?与标点符号相似的字符怎么办?UTS #39 中的其他建议怎么办?混合脚本标识符怎么办?
  6. 应该使用哪种规范化形式,NFC 还是 NFKC?
  7. 是否要求源代码以规范化形式存在?

参考


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

上次修改时间: 2023-09-09 17:39:29 GMT