【问题标题】:Python3 and combining DiacriticsPython3 和组合变音符号
【发布时间】:2019-07-13 21:26:09
【问题描述】:

我在 python3 中遇到了 Unicode 问题,我似乎无法理解为什么会这样。

symbol= "ῇ̣"
print(len(symbol))
>>>>2

这封信来自一个词:ἐ̣ν̣τ̣ῇ̣[αὐτ]ῇ,其中我结合了变音符号。我想在 Python 3 中进行统计分析并将结果存储在数据库中,问题是我还将字符的位置(索引)存储在文本中。数据库应用程序正确地将示例中的符号变量计为一个字符,而 Python 将其计为两个 - 丢弃了整个索引。

该项目要求我保留变音符号,因此我不能简单地忽略它们或在字符串上添加.replace("combining diacritical mark","")

由于 Python3 将 unicode 作为字符串的默认设置,我对此有点傻眼。

我尝试使用来自希腊口音的base()strip()strip_length() 方法:https://pypi.org/project/greek-accentuation/,但这也无济于事。

项目要求是:

  • 检测属于字符的字母表(OK)
  • 存储字符串位置(需要在数据库中突出显示)(NotOK)
  • 能够处理混合在一个字符串中的多种语言/字母。 (好的)
  • 遍历 CSV 输入。 (好的)
  • 忽略一组预定义的字符串 (OK)
  • 忽略符合特定条件的字符串集(OK)

这是该项目的简化代码:

# -*- coding: utf-8 -*-
import csv
from alphabet_detector import AlphabetDetector
ad = AlphabetDetector()
with open("tbltext.csv", "r", encoding="utf8") as txt:
    data = csv.reader(txt)
    for row in data:
        text = row[1]
        ### Here I have some string manipulation (lowering everything, replacing the predefined set of strings by equal-length '-',...)
        ###then I use the ad-module to detect the language by looping over my characters, this is where it goes wrong.
        for letter in text:
            lang = ad.detect_alphabet(letter)

如果我使用这个词:ἐ̣ν̣τ̣ῇ̣[αὐτ]ῇ 作为 forloop 的示例;我的结果是:

>>> word = "ἐ̣ν̣τ̣ῇ̣[αὐτ]ῇ"
>>> for letter in word:
...     print(letter)
...
ἐ
̣
ν
̣
τ
̣
ῇ
̣
[
α
ὐ
τ
]
ῇ

如何让 Python 将带有组合变音标记的字母视为一个字母,而不是让它分别打印字母和变音标记?

【问题讨论】:

  • 我忘了把这个添加到我原来的问题中:这里是为 Ruby 描述的一个类似问题,但我找不到与提到的 UnicodeUtils.eachGrapheme() 方法相同的 Python 模型:@ 987654322@
  • 看起来很适合python bug tracker
  • @AzatIbrakov:不,2 是正确的行为
  • @Clueless_captain 你可以edit你的帖子。

标签: python-3.x unicode diacritics


【解决方案1】:

字符串的长度为 2,所以这是正确的:两个代码点:

>>> list(hex(ord(c)) for c in symbol)
['0x1fc7', '0x323']
>>> list(unicodedata.name(c) for c in symbol)
['GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI', 'COMBINING DOT BELOW']

所以你不应该使用len来计算字符数。

您可以计算非组合字符,所以:

>>> import unicodedata
>>> len(''.join(ch for ch in symbol if unicodedata.combining(ch) == 0))
1

来自:How do I get the "visible" length of a combining Unicode string in Python?(但我将它移植到了 python3)。

但这也不是最优解,取决于计数字符的范围。我认为在你的情况下就足够了,但是字体可以将字符合并到 ligatures 中。在某些语言中,它们是视觉上新的(并且非常不同的)字符(不像西方语言中的连字)。

最后一条评论:我认为你应该规范化字符串。使用上面的代码,在这种情况下没关系,但在其他情况下,您可能会得到不同的结果。尤其是如果有人使用可战斗字符(例如单位的 mu,或 Eszett,而不是真正的希腊字符)。

【讨论】:

  • 我正在寻求帮助,关于如何命名这样的函数
  • 好的,现在说得通了。
  • 感谢您的解释和建议。您可以将其称为 screen_length 或 combined_length (因为这种行为仅限于“组合字符”的 unicode 块中的字符。)我一直觉得奇怪的是 DB 和 Notepad++ 将组合字符识别为单个长度单位;虽然我不得不忍受它。我还没有想过对这些情况使用规范化,也感谢您指出这一点!
  • Notetepad++ 在视觉上工作,你不能介于字符和组合字符之间。对于 python,您通常需要解析并获取代码点(例如for i in range(len(my_string))),因此您需要处理每个单独的代码点。如果一个“字符”可以有数百个代码点,并且不容易转换为数字/字节,那将更加复杂)。语言和字符很复杂。 Unicode 有很多描述和问题,但没有“一刀切”。通过单一编码(unicode)已经取得了巨大的成功。
猜你喜欢
  • 2018-01-31
  • 1970-01-01
  • 1970-01-01
  • 2021-07-08
  • 2011-05-12
  • 1970-01-01
  • 2011-03-24
  • 2010-10-23
  • 2016-01-26
相关资源
最近更新 更多