【问题标题】:Strange behavior of Python's upper() methodPython的upper()方法的奇怪行为
【发布时间】:2019-12-03 01:19:54
【问题描述】:

当我偶然发现一个奇怪的结果时,我正在使用一个涉及 str.upper() 和 str.lower() 函数的 Python 脚本。当我将字母 (带有 dasia 和 prosgegrammeni 的大写字母,U+1F89)传递给upper() 函数时,结果是ἉΙ,而不是预期的

要重现的代码:

print('ᾉ'.upper())

打印

ἉΙ

这是预期的行为还是某种错误?

编辑:我替换为正确的字符。

【问题讨论】:

  • 更奇怪的是,'a'.upper().lower() 按预期回馈'a',但'ᾉ'.upper().lower() 回馈'ἁι'
  • 这可能是一个标准化问题。这里的upper 方法正在执行将单个字符转换为两个字符的有损转换。结果字符串不包含小写版本应将两者“组合”成单个字符的信息。
  • 嗯,这有点烦人……有什么办法可以避免吗?
  • @Darmo:您可能正在寻找'ᾉ'.title() 而不是'ᾉ'.upper()Here 是标题和大写不同的所有 unicode 字符的列表。

标签: python unicode python-3.7 uppercase


【解决方案1】:

检查符号(例如,使用this online tool)告诉我你有一个U+1F89 GREEK CAPITAL LETTER ALPHA WITH DASIA AND YPROSGEGRAMMENI(不是U+1F88)。

查找该术语,我们在iota subscripts 上获得了一篇维基百科文章:

在仅大写字母的环境中,它再次表示为略微缩小的 iota(小于常规小写 iota)或全尺寸的大写 Iota。

您需要有古希腊知识的人来验证这一点,但乍一看,结果在逻辑上与您最初的结果相同。


现在,仔细阅读 Unicode 标准的第 3.13 节会发现,您所拥有的符号实际上被明确提及为一个例外:

在 D145 中的情况折叠之前调用规范分解(NFD 规范化)是为了捕获非常罕见的边缘情况。在大小写折叠之前不需要规范化,除了字符 U+0345 ncombining greek ypogegrammeni 和任何将它作为其规范分解的一部分的字符,例如U+1FC3 greek small letter eta with ypogegrammeni

此外,根据维基百科,

对于全大写(“大写”),Unicode 还规定了一个特殊的大小写映射规则,根据该规则,小写字母应映射到大写字母和大写字母的组合(ᾳ → ΑΙ)。该规则不仅用双元音的表示代替了单音元的表示,而且还破坏了数字环境中任何大写过程的可逆性,因为大写字母和大写 iota 的组合通常会转换回小写字母和小写 iota .

显然您在 Unicode 标准中遇到了一个奇怪的边缘情况,所以这是意料之中的,而不是 Python 的 str.upper() 中的错误。

【讨论】:

  • 我把字母弄乱了,我找不到如何编辑我的问题。
【解决方案2】:

不是答案,但这可能是一个错误吗?同样的事情在 Python2 中也能完美运行。

Python 2.7.15rc1 (default, Nov 12 2018, 14:31:15)
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print("ᾉ".upper())
ᾉ

Python 3

Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print("ᾉ".upper())
ἉΙ

Python 3 documentation 表示使用的大写算法在 Unicode 标准的第 3.13 节中有所描述。

我找不到与 python 2 中使用的相同的信息。

【讨论】:

    猜你喜欢
    • 2013-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-14
    • 1970-01-01
    相关资源
    最近更新 更多