为什么这个土耳其字符在我小写时会被破坏?

mot*_*oth 3 python turkish utf-8 case-sensitive character-encoding

我试图将包含土耳其语字符的单词转换为小写.

从utf-8编码的文件中读取单词:

with open(filepath,'r', encoding='utf8') as f:
            text=f.read().lower()
Run Code Online (Sandbox Code Playgroud)

当我尝试转换为小写时,土耳其语字符gets被破坏.但是,当我尝试转换为大写时,它工作正常.

这是示例代码:

str = '??birli?i'
print(str)
print(str.lower())
Run Code Online (Sandbox Code Playgroud)

以下是它在损坏时的外观:

这就是它被破坏时的样子

这里发生了什么?

一些可能有用的信息:

  • 我正在使用Windows 10 cmd提示符
  • Python版本3.6.0
  • chcp设置为65001

Zer*_*eus 6

它没有被破坏.

土耳其语有一个点缀的小写字母i和一个无点的小写字母?,同样是一个点缀的大写字母?和一个无点的大写字母I.

这在将虚线大写转换?为小写时提出了一个挑战:如何保留信息,如果需要将其转换回大写,则应将其转换回虚线?

Unicode解决了这个问题如下:当?转换为小写时,它实际上转换为标准拉丁i 加上组合字符U + 0307"COMBINING DOT ABOVE".您所看到的是您的终端无法正确呈现(或者更重要的是,避免渲染)组合字符,并且与Python无关.

您可以看到这种情况正在发生unicodedata.name():

>>> import unicodedata
>>> [unicodedata.name(c) for c in '?']
['LATIN CAPITAL LETTER I WITH DOT ABOVE']
>>> [unicodedata.name(c) for c in '?'.lower()]
['LATIN SMALL LETTER I', 'COMBINING DOT ABOVE']
Run Code Online (Sandbox Code Playgroud)

...虽然,在一个正常工作且配置正确的终端中,它会呈现没有任何问题:

>>> '?'.lower()
'i?'
Run Code Online (Sandbox Code Playgroud)

作为一个侧面说明,如果你做的将其转换回为大写,它会留在分解形式:

>>> [unicodedata.name(c) for c in '?'.lower().upper()]
['LATIN CAPITAL LETTER I', 'COMBINING DOT ABOVE']
Run Code Online (Sandbox Code Playgroud)

...虽然你可以重新组合它unicodedata.normalize():

>>> [unicodedata.name(c) for c in unicodedata.normalize('NFC','?'.lower().upper())]
['LATIN CAPITAL LETTER I WITH DOT ABOVE']
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅: