Python允许使用unicode标识符。我定义了Xᵘ = 42
,期望XU
和Xᵤ
产生NameError
。但实际上,当我定义Xᵘ
时,Python(默默地?)将Xᵘ
转换为Xu
,这让我觉得有些单调的事情要做。为什么会这样?
>>> Xᵘ = 42
>>> print((Xu, Xᵘ, Xᵤ))
(42, 42, 42)
答案 0 :(得分:12)
Python将所有标识符转换为NFKC normal form;来自参考文档的Identifiers section:
解析时,所有标识符都转换为正常格式NFKC;标识符的比较基于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(抽象解析树)时,任何标识符都被标准化。
标识符被规范化以避免许多潜在的“看似相似”的错误,否则您最终可能会同时使用find()
(使用U+FB01 LATIN SMALL LIGATURE FI字符后跟ASCII nd
字符)和find()
,并想知道为什么你的代码有错误。
答案 1 :(得分:2)
Python,从3.0版开始,支持非ASCII标识符。当使用NFKC规范化转换解析标识符时,标准化值相同的任何标识符都被视为相同的标识符。
有关详细信息,请参阅PEP 3131。 https://www.python.org/dev/peps/pep-3131/