当前位置:  开发笔记 > 编程语言 > 正文

标识符规范化:为什么微标志转换为希腊字母mu?

如何解决《标识符规范化:为什么微标志转换为希腊字母mu?》经验,为你挑选了1个好方法。

我偶然发现了以下奇怪的情况:

>>> class Test:
        µ = 'foo'

>>> Test.µ
'foo'
>>> getattr(Test, 'µ')
Traceback (most recent call last):
  File "", line 1, in 
    getattr(Test, 'µ')
AttributeError: type object 'Test' has no attribute 'µ'
>>> 'µ'.encode(), dir(Test)[-1].encode()
(b'\xc2\xb5', b'\xce\xbc')

我输入的字符始终是键盘上的μ符号,但由于某种原因它会被转换.为什么会这样?



1> poke..:

这里涉及两个不同的角色.一个是MICRO SIGN,它是键盘上的一个,另一个是GREEK SMALL LETTER MU.

要了解发生了什么,我们应该看看Python如何在语言参考中定义标识符:

identifier   ::=  xid_start xid_continue*
id_start     ::=  
id_continue  ::=  
xid_start    ::=  
xid_continue ::=  

我们的字符MICRO SIGN和GREEK SMALL LETTER MU都是Llunicode组(小写字母)的一部分,因此它们都可以在标识符的任何位置使用.现在请注意,identifier实际引用的定义是xid_startxid_continue,并且它们被定义为相应的非x定义中的所有字符,其NFKC规范化导致标识符的有效字符序列.

Python显然只关心标准化的标准化形式.这有点如下:

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

NFKC是一种Unicode规范化,可将字符分解为单个部分.MICRO SIGN分解为GREEK SMALL LETTER MU,这就是那里正在发生的事情.

还有很多其他角色也会受到此规范化的影响.另一个例子是OHM SIGN,它分解为GREEK CAPITAL LETTER OMEGA.使用它作为标识符给出了类似的结果,这里使用locals显示:

>>> ? = 'bar'
>>> locals()['?']
Traceback (most recent call last):
  File "", line 1, in 
    locals()['?']
KeyError: '?'
>>> [k for k, v in locals().items() if v == 'bar'][0].encode()
b'\xce\xa9'
>>> '?'.encode()
b'\xe2\x84\xa6'

所以最后,这只是Python所做的事情.不幸的是,没有一种很好的方法可以检测到这种行为,从而导致错误,例如显示的错误.通常,当标识符仅被称为标识符时,即它像真实变量或属性一样使用时,一切都会正常:标准化每次运行,并找到标识符.

唯一的问题是基于字符串的访问.字符串只是字符串,当然没有规范化发生(这只是一个坏主意).这里显示的两种方式,getattr并且locals,无论在字典操作.getattr()通过对象访问对象的属性__dict__,并locals()返回一个字典.在字典中,键可以是任何字符串,因此在那里有一个MICRO SIGN或OHM SIGN是完全没问题的.

在这些情况下,您需要记住自己执行标准化.我们可以利用unicodedata.normalize它,这也允许我们从内部locals()(或使用getattr)正确地获取我们的价值:

>>> normalized_ohm = unicodedata.normalize('NFKC', '?')
>>> locals()[normalized_ohm]
'bar'

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有