Unicode 标识符中的下标和上标,为什么 Python 会考虑 XU == Xu == Xu?



Python 允许 unicode 标识符。 我定义了Xᵘ = 42,期望XUXᵤ导致NameError。 但实际上,当我定义Xᵘ时,Python(默默地?)将Xᵘ变成了Xu,这让我觉得有点不python的事情。 为什么会这样?

>>> Xᵘ = 42
>>> print((Xu, Xᵘ, Xᵤ))
(42, 42, 42)

Python 将所有标识符转换为其 NFKC 范式;从参考文档的标识符部分:

解析时,所有标识符都转换为正常形式的NFKC;标识符的比较基于NFKC。

超级和下标字符的NFKC形式都是小写u

>>> import unicodedata
>>> unicodedata.normalize('NFKC', 'Xᵘ Xᵤ')
'Xu Xu'

所以最后,你所拥有的只是一个标识符,Xu

>>> import dis
>>> dis.dis(compile('Xᵘ = 42nprint((Xu, Xᵘ, Xᵤ))', '', 'exec'))
1           0 LOAD_CONST               0 (42)
2 STORE_NAME               0 (Xu)
2           4 LOAD_NAME                1 (print)
6 LOAD_NAME                0 (Xu)
8 LOAD_NAME                0 (Xu)
10 LOAD_NAME                0 (Xu)
12 BUILD_TUPLE              3
14 CALL_FUNCTION            1
16 POP_TOP
18 LOAD_CONST               1 (None)
20 RETURN_VALUE

上面对编译字节码的反汇编表明标识符在编译过程中已被规范化;这发生在解析过程中,任何标识符在创建编译器用于生成字节码的 AST(抽象解析树)时都会被规范化。

标识符被规范化以避免许多潜在的"相似"错误,否则您最终可能会同时使用find()(使用U+FB01 拉丁小连字 FI字符,后跟 ASCIInd字符)和find()并想知道为什么您的代码有错误。

Python,从3.0版本开始,支持非ASCII标识符。解析时,标识符使用 NFKC 规范化进行转换,规范化值相同的任何标识符都被视为相同的标识符。

有关更多详细信息,请参阅 PEP 3131。 https://www.python.org/dev/peps/pep-3131/

最新更新