当前位置: 首页 > 面试题库 >

标识符归一化:为什么微符号会转换为希腊字母mu?

苏选
2023-03-14
问题内容

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

>>> class Test:
        µ = 'foo'

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

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


问题答案:

这里涉及两个不同的字符。一个是MICRO
SIGN
,它是键盘上的一个,另一个是GREEK
SMALL LETTER MU

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

identifier   ::=  xid_start xid_continue*
id_start     ::=  <all characters in general categories Lu, Ll, Lt, Lm, Lo, Nl, the underscore, and characters with the Other_ID_Start property>
id_continue  ::=  <all characters in id_start, plus characters in the categories Mn, Mc, Nd, Pc and others with the Other_ID_Continue property>
xid_start    ::=  <all characters in id_start whose NFKC normalization is in "id_start xid_continue*">
xid_continue ::=  <all characters in id_continue whose NFKC normalization is in "id_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 "<pyshell#1>", line 1, in <module>
    locals()['Ω']
KeyError: 'Ω'
>>> [k for k, v in locals().items() if v == 'bar'][0].encode()
b'\xce\xa9'
>>> 'Ω'.encode()
b'\xe2\x84\xa6'

因此,最后,这只是Python要做的事情。不幸的是,没有真正好的方法可以检测到此行为,从而导致出现如图所示的错误。通常,当标识符仅被称为标识符,即像真实变量或属性一样使用时,一切都会好起来的:每次都运行规范化,然后找到标识符。

唯一的问题是基于字符串的访问。字符串只是字符串,当然不会发生规范化(那将是一个坏主意)。此处显示的两种方式getattrlocals都对词典起作用。getattr()通过对象的访问对象的属性__dict__,并locals()返回字典。而且在字典中,键可以是任何字符串,因此在其中带有MICRO
SIGN或OHM SIGN是完全可以的。

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

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


 类似资料:
  • 问题内容: Oracle Java Community网站上的一篇文章提供了以下方法作为示例(对于JPA Converter,但这并不相关): 将String y强制转换为String val有什么用?有正当的理由吗? 原始文章:JPA的新增功能 问题答案: 这样的转换是完全没有必要的。我可以想象那是以前 但是后来参数类型更改为,而作者只是忘了删除强制类型转换。

  • 问题内容: 问题是,正如您所知道的,Unicode图表中有成千上万个字符,我想将所有类似的字符转换为英文字母。 例如,这里有一些转换: 我发现字母A / a有20多个版本。而且我不知道如何对它们进行分类。它们看起来像大海捞针。 Unicode字符的完整列表位于http://www.ssec.wisc.edu/~tomw/java/unicode.html 或http://unicode.org/c

  • 所以我是计算机科学的新手,我们被要求做的一件事是尝试创建一个程序,首先将用户输入的一个单词转换成一个数字串,a=1,b=2,z=26等等,还有一些其他的事情,因为它们是扩展,我现在不想讨论。诚然,她说她不介意我们完成它,因为这是我们今天的第一节java课程。 有鉴于此,有人能给我一些关于如何做到这一点的建议吗?我不想让一段完整的代码完全做到这一点,因为我需要学习,因此非常感谢指导之手。到目前为止,

  • 在我的生产级应用程序中,我正在研究一些与unicode字符相关的问题,比如中文/日语字符串。 我的应用程序有一个启动程序和一个配置文件,它设置了运行JVM可以使用的所有参数。此配置文件作为命令行参数的一部分传递。 所以我创建了一个小程序来测试这个场景,该程序的工作是将一个文件路径作为命令行参数的一部分,打印它并读取该文件的内容。在运行之前,它看起来与上面类似,即“some/path/和/????.

  • 为什么在C 11中无符号短*无符号短转换为int? int太小,无法处理这行代码显示的最大值。 MinGW 4.9.2溢流 因为(来源) USHRT_MAX=65535 (2^16-1)或更大* INT_MAX=32767 (2^15-1)或更大* 和(2^16-1)*(2^16-1)=~2^32。 这个解决方案会有什么问题吗? 此程序 给出输出 在…上 两者都有 这证明在这些编译器上,被转换为。

  • 问题内容: 在Java中,是否有一种简单而优雅的方法将无符号字节值转换为有符号字节值?例如,如果我所拥有的只是int值240(二进制(24位+ 11110000)= 32bits),如何获得该int的带符号值? 问题答案: 除了,Java没有其他无符号值。考虑以下代码段: 结果将为-1,因为最低的8位已复制到byte变量中。