标识符中的Unicode下标和上标,为什么Python考虑XU == Xᵘ == Xᵤ?
Unicode subscripts and superscripts in identifiers, why does Python consider XU == Xᵘ == Xᵤ?
Python 允许 unicode 标识符。我定义了 Xᵘ = 42
,期望 XU
和 Xᵤ
产生 NameError
。但实际上,当我定义 Xᵘ
时,Python(默默地?)将 Xᵘ
转换为 Xu
,这让我觉得有些不符合 Python 的做法。为什么会这样?
>>> Xᵘ = 42
>>> print((Xu, Xᵘ, Xᵤ))
(42, 42, 42)
Python,从 3.0 版开始,支持非 ASCII 标识符。解析标识符时使用 NFKC 规范化进行转换,任何规范化值相同的标识符都被视为相同的标识符。
有关详细信息,请参阅 PEP 3131。 https://www.python.org/dev/peps/pep-3131/
Python 将所有标识符转换为参考文档的 NFKC normal form; from the Identifiers section:
All identifiers are converted into the normal form NFKC while parsing; comparison of identifiers is based on NFKC.
上标和下标字符的NFKC形式都是小写u
:
>>> import unicodedata
>>> unicodedata.normalize('NFKC', 'Xᵘ Xᵤ')
'Xu Xu'
所以最后,您只有一个标识符,Xu
:
>>> import dis
>>> dis.dis(compile('Xᵘ = 42\nprint((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(抽象解析树)时,任何标识符都会被规范化。
标识符被规范化以避免许多潜在的 'look-alike' 错误,否则你最终可能会同时使用 find()
(使用 U+FB01 LATIN SMALL LIGATURE FI 字符后跟 ASCII nd
字符)和 find()
并想知道为什么你的代码有错误。
Python 允许 unicode 标识符。我定义了 Xᵘ = 42
,期望 XU
和 Xᵤ
产生 NameError
。但实际上,当我定义 Xᵘ
时,Python(默默地?)将 Xᵘ
转换为 Xu
,这让我觉得有些不符合 Python 的做法。为什么会这样?
>>> Xᵘ = 42
>>> print((Xu, Xᵘ, Xᵤ))
(42, 42, 42)
Python,从 3.0 版开始,支持非 ASCII 标识符。解析标识符时使用 NFKC 规范化进行转换,任何规范化值相同的标识符都被视为相同的标识符。
有关详细信息,请参阅 PEP 3131。 https://www.python.org/dev/peps/pep-3131/
Python 将所有标识符转换为参考文档的 NFKC normal form; from the Identifiers section:
All identifiers are converted into the normal form NFKC while parsing; comparison of identifiers is based on NFKC.
上标和下标字符的NFKC形式都是小写u
:
>>> import unicodedata
>>> unicodedata.normalize('NFKC', 'Xᵘ Xᵤ')
'Xu Xu'
所以最后,您只有一个标识符,Xu
:
>>> import dis
>>> dis.dis(compile('Xᵘ = 42\nprint((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(抽象解析树)时,任何标识符都会被规范化。
标识符被规范化以避免许多潜在的 'look-alike' 错误,否则你最终可能会同时使用 find()
(使用 U+FB01 LATIN SMALL LIGATURE FI 字符后跟 ASCII nd
字符)和 find()
并想知道为什么你的代码有错误。