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

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,并根据下文定义的阐述和更改进行调整。

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

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

关于哪些字符具有 XID_Start 或 XID_Continue 属性的精确规范可以在 Python 使用的 Unicode 数据(撰写本 PEP 时为 4.1)的 DerivedCoreProperties 文件中找到。作为参考,下面给出了这些集合的构造规则。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。

列出 Unicode 4.1 所有有效标识符字符的非规范性 HTML 文件可在 https://web.archive.org/web/20081016132748/http://www.dcl.hpi.uni-potsdam.de/home/loewis/table-3131.html 找到。

策略规范

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

作为一个选项,此规范可以应用于 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,其中讨论了 Unicode 标识符的安全机制。目前尚不清楚它如何精确地适用于此 PEP;可能的后果是

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

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

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

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

一些人希望在运行时选择支持此 PEP 的选项;关于该选项具体应该是什么,以及其默认值应该是什么,意见不一。Guido van Rossum 评论道,传递给解释器的全局标志是不可接受的,因为它会应用于所有模块。

讨论

Ka-Ping Yee 总结了讨论和进一步的异议如下

  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

最后修改:2025-02-11 05:10:05 GMT