我目前正在学习Python,作为斯洛文尼亚语,我经常使用UTF-8字符来测试我的程序。通常一切正常,但有一个我无法超越的捕获。即使我在文件顶部声明了编码,当我尝试反转包含特殊字符的字符串时它也会失败
#-*- coding: utf-8 -*-
a = "čšž"
print a #prints čšž
b = a[::-1]
print b #prints �šō� instead of žšč
有没有办法解决这个问题?
答案 0 :(得分:15)
Python 2字符串是字节字符串,UTF-8编码文本每个字符使用多个字节。仅仅因为你的终端设法将UTF-8字节解释为字符,并不意味着Python知道哪个字节形成一个UTF-8字符。
您的bytestring由6个字节组成,每两个字节组成一个字符:
>>> a = "čšž"
>>> a
'\xc4\x8d\xc5\xa1\xc5\xbe'
但是,UTF-8使用的字节数取决于Unicode标准中字符定义的位置; ASCII字符(Unicode标准中的前128个字符)每个只需要1个字节,许多表情符号需要4个字节!
在UTF-8中,所有内容;反转上面的字节串可以反转字节,就UTF-8标准而言会产生一些乱码,但是中间的4个字节发生是有效的UTF-8序列(对于{{1} }和š
):
ō
您必须将字节字符串解码为>>> a[::-1]
'\xbe\xc5\xa1\xc5\x8d\xc4'
-----~~~~~~~~^^^^^^^^####
| š ō |
\ \
invalid UTF8 byte opening UTF-8 byte missing a second byte
对象,该对象由单个字符组成。反转该对象可以得到正确的结果:
unicode
您始终可以将对象重新编码为UTF-8:
b = a.decode('utf8')[::-1]
print b
请注意,在Unicode中,当使用combining characters时,在翻转文本时仍会遇到问题。使用组合字符反转文本会将那些组合字符放在前面而不是放在它们组合后的字符之后,因此它们会与错误的字符组合:
b = a.decode('utf8')[::-1].encode('utf8')
你可以通过将Unicode数据转换为其标准化形式(取代1代码点形式的组合)来避免这种情况,但是还有很多其他奇特的Unicode字符在字符串反转方面不能很好地发挥作用。