Python反转UTF-8字符串

Den*_*nič 7 python string reverse character utf-8

我目前正在学习Python,作为斯洛文尼亚语,我经常使用UTF-8字符来测试我的程序.通常一切正常,但有一个我无法超越的捕获.即使我在文件顶部声明了编码,但当我尝试反转包含特殊字符的字符串时,它也会失败

#-*- coding: utf-8 -*-

a = "?šž"
print a    #prints ?šž
b = a[::-1]
print b    #prints ?š?? instead of žš?
Run Code Online (Sandbox Code Playgroud)

有没有办法解决这个问题?

Mar*_*ers 15

Python 2字符串是字节字符串,UTF-8编码文本每个字符使用多个字节.仅仅因为您的终端设法将UTF-8字节解释为字符,并不意味着Python知道哪个字节形成一个UTF-8字符.

您的bytestring由6个字节组成,每两个字节组成一个字符:

>>> a = "?šž"
>>> a
'\xc4\x8d\xc5\xa1\xc5\xbe'
Run Code Online (Sandbox Code Playgroud)

但是,UTF-8使用的字节数取决于Unicode标准中字符定义的位置; ASCII字符(Unicode标准中的前128个字符)每个只需要1个字节,许多表情符号需要4个字节!

在UTF-8中,秩序就是一切 ; 与上述相反的字节串反转的字节数,从而导致一些乱码只要UTF-8标准而言,但中间的4个字节正好发生是有效的UTF-8序列(š?):

>>> a[::-1]
'\xbe\xc5\xa1\xc5\x8d\xc4'
-----~~~~~~~~^^^^^^^^####
  |     š       ?      |
  \                    \
   invalid UTF8 byte    opening UTF-8 byte missing a second byte
Run Code Online (Sandbox Code Playgroud)

您必须将字节字符串解码为一个unicode对象,该对象由单个字符组成.反转该对象可以获得正确的结果:

b = a.decode('utf8')[::-1]
print b
Run Code Online (Sandbox Code Playgroud)

您始终可以将对象再次编码回UTF-8:

b = a.decode('utf8')[::-1].encode('utf8')
Run Code Online (Sandbox Code Playgroud)

请注意,在Unicode中,当使用组合字符时,在反转文本时仍会遇到问题.使用组合字符反转文本会将那些组合字符放在前面而不是放在它们组合后的字符之后,因此它们将与错误的字符组合:

>>> print u'e\u0301a'
éa
>>> print u'e\u0301a'[::-1]
áe
Run Code Online (Sandbox Code Playgroud)

你可以通过将Unicode数据转换为其标准化形式(它取代了1代码点形式的组合)来避免这种情况,但是还有很多其他奇特的Unicode字符在字符串反转时效果不佳.