欲仙欲死的字符编码问题请教

2015-06-21 17:45:55 +08:00
 echo1937
先引用一段教程里的话:
Python 2.6中这种自由混合字符串类型的方法,只有在字符串和unicode对象的编码类型兼容的情况下才有效:
>>> S = 'A\xC4B\xE8C' # Can't mix if incompatible
>>> U = u'A\xC4B\xE8C'
>>> S + U
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 1: ordinal not in range(128)
>>> S.decode('latin-1') + U # Manual conversion still required
u'A\xc4B\xe8CA\xc4B\xe8C'
>>> print S.decode('latin-1') + U
AÄBèCAÄBèC

问题是:
1.S编码类型是ascii吧?U编码类型是latin-1吧?
2.latin-1是兼容ascii的吧,为什么还需要手动转换呢?
2830 次点击
所在节点    Python
9 条回复
imn1
2015-06-21 17:55:12 +08:00
ascii 是0-127
latin-1是 0-255
lilydjwg
2015-06-21 17:57:58 +08:00
U 是 Unicode 字符串,没有编码一说。当 str 和 unicode 相加时,Python 2 尝试将 str 以 ASCII 解码,所以出错了。
Sylv
2015-06-21 18:02:41 +08:00
S 是 latin-1 编码的 str 类型字符串
U 是 unicode 类型字符串,存储的不是编码,而是码点

S + U:是一个 str 类型字符串加一个 unicode 类型字符串,类型不一致,所以 Python 会把 str 类型的 S 用默认编码 ascii 转换为 unicode 类型。因此 S + U 等价于:S.decode('ascii') + U。

而字符串 S 是不能用 ascii 编码转换为 unicode 的,要用 latin-1编码:
>>> S.decode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 1: ordinal not in range(128)
>>> S.decode('latin-1')
u'A\xc4B\xe8C'

因此想要不报错需要:
S.decode('latin-1') + U
onlyice
2015-06-21 18:09:20 +08:00
楼上正解
Sylv
2015-06-21 18:18:16 +08:00
另:'\xC4' 不是 4 个字符,而是 1 个字符,其编码值为 16 进制的 C4,也就是 10 进制的 196。如一楼所说,ascii 编码的范围是 0-127,所以 '\xC4' 并不在 ascii 编码范围内,那么 S 编码类型就不会是 ascii。
echo1937
2015-06-21 19:26:25 +08:00
@Sylv 已感谢,另请教什么是码点,Google未果。
Sylv
2015-06-21 19:40:51 +08:00
shuax
2015-06-21 20:00:18 +08:00
每个用python的人,都被编码折磨过
fengjianxinghun
2015-06-25 11:42:16 +08:00
python2唯一坑爹的地方就是str 和unicode这里。。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/200191

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX