无法将大写转换为“ß”(德语字符 eszett)

unable to get uppercase to 'ß' (german character called eszett)

你好,我必须将字符串列转换为大写版本,但是当字符串中存在“ß”时,它会在大写时更改为 'SS' 我明白这是因为,早期的 'SS' 被认为是 'ß' 的大写。但是在 2017 年,'SS' 和大写 'ß' 都被允许。

它的 unicode 版本也可用。

我有以下问题:

  1. 为什么 python 不将其转换为大写 'ß'。

  2. 难道是因为python内嵌了unicode标准?如何知道 python/jupyter notebook 使用的是哪个 unicode 标准?

  3. 有没有办法在 python 中获取大写字母 'ß' 而不是 'SS'?

我是

这也是许多其他语言的行为,您可以像这样解决它:

my_string.replace('ß', 'ẞ').upper()

各种 Python 版本使用特定的 Unicode 版本。例如,我认为原始 Python 3.7 使用 Unicode 10.0.0 ,而它 可用的字母(自 Unicode 5.1,我相信),仍然列出旧的 upper/lower 映射:

00DF ß LATIN SMALL LETTER SHARP S
    = Eszett
    - German
    - uppercase is "SS"
    - nonstandard uppercase is 1E9E ẞ
1E9E ẞ LATIN CAPITAL LETTER SHARP S
    - lowercase is 00DF ß

即使是 最新的 标准,13.0.0(尽管此更改是在 11.0.0 中进行的),似乎也允许自由裁量权作为如何将低位转换为高位:

00DF ß LATIN SMALL LETTER SHARP S
    = Eszett
    - German
    - not used in Swiss High German
    - uppercase is "SS" or 1E9E ẞ
1E9E ẞ LATIN CAPITAL LETTER SHARP S
    - not used in Swiss High German
    - lowercase is 00DF ß

以下 table 将某些 Python 版本映射到 Unicode 版本:

 Python     Unicode
--------    -------
   3.5.9      8.0.0
  3.6.11      9.0.0
   3.7.8     11.0.0
3.8.4rc1     12.1.0
 3.9.0b4     13.0.0
3.10.0a0     13.0.0

因此您可能不得不等待更高版本的 Unicode(以及 使用 那个 Unicode 版本的 Python,其中映射不太理想-比 uppercase is "SS" or 1E9E ẞ" 少。但这实际上可能被 Unicode stability policy 部分排除:

If two characters form a case pair in a version of Unicode, they will remain a case pair in each subsequent version of Unicode. If two characters do not form a case pair in a version of Unicode, they will never become a case pair in any subsequent version of Unicode.

你可以用一个新引入的角色来制作一个案例对,假设你想与之配对的那个尚未配对,但这里不允许这样做,因为:

  • 这个“新”字符早在 Unicode 5.1 中就已引入;和
  • 我们要与之配对的角色已经配对。

我的阅读让我相信解决此问题的唯一方法而不违反该政策,是引入两个 大小写对中的字符,例如:

ß LATIN SMALL LETTER SHARP S THAT IS LOWER OF ẞ
ẞ LATIN CAPITAL LETTER SHARP S THAT IS UPPER OF ß

但是,我不确定它能否通过 Unicode 联盟的愚蠢过滤器:-)

对于立即修复,您可以简单地将特定字符强制为您想要的任何字符,然后再应用内置的大小写更改,例如:

to_be_uppered.replace('ß', 'ẞ').upper()
to_be_lowered.replace('ẞ', 'ß').lower()

后者似乎是不必要的,至少在我的版本 Python 3.8.2 中是这样。我将它包括在内以防万一早期的 Python 版本可能需要它。甚至可能值得将这些放入自定义 my_upper()my_lower() 函数中,如果事实证明还有更多这样的情况需要处理。

应用 (+1):

my_string.replace('ß', 'ẞ').upper()

我看不到任何其他解决方案,因为在 Unicode 文档中发现了某种政治正确性

  • 来自 Character Properties, Case Mappings & Names FAQ:

  • Q: Is all of the Unicode case mapping information in UnicodeData.txt?

    A:不。UnicodeData.txt 文件包含所有一对一的案例映射。由于许多解析器在构建时都期望 UnicodeData.txt 在每个 case 映射字段中最多只有一个字符,因此添加了文件 SpecialCasing.txt 以提供一对多映射,例如需要大写 ß(U+00DF 拉丁文小写字母 S )。此外,CaseFolding.txt 包含用于大小写折叠和无大小写匹配的附加映射。有关详细信息,请参阅第 5.18 节,Unicode 标准中的大小写映射。

  • Q: Why does ß (U+00DF LATIN SMALL LETTER SHARP S) not uppercase to U+1E9E LATIN CAPITAL LETTER SHARP S by default?

    答:在标准德语正字法中,升号 s(“ß”)曾经完全大写为两个大写 S 字符的序列。这种长期存在的做法反映在 Unicode 中的默认大小写映射中。出于排版原因或避免歧义,有时首选 ß 的大写形式,例如护照中的大写姓名。它在 Unicode 标准中编码为 U+1E9E。虽然这个字符没有被广泛使用,但现在在官方正字法中被认为是除“SS”之外的 ß 的可选大写形式。因为它只是一个可选的替代方案,所以到“SS”的原始映射保留在 Unicode 字符属性中。

  • 来自 SpecialCasing.txt

    德国es-zed比较特殊--法线映射到SS

  • from UnicodeData.txt (see Uppercase mapping and Lowercase mapping fields as defined in UnicodeData File Format): 小写映射被定义拉丁大写字母尖锐S而大写拉丁小写字母升号 S 的映射不是…

 00DF;LATIN SMALL LETTER SHARP S;Ll;0;L;;;;;N;;;;;
 1E9E;LATIN CAPITAL LETTER SHARP S;Lu;0;L;;;;;N;;;;00DF;