考虑下面的代码片段:
import sys
for i in range(128, 256):
sys.stdout.write(chr(i))
运行这与Python 2,看看结果与hexdump -C
:
00000000 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f |................|
等等。没有惊喜;从0x80
到0xff
的128个字节。
做同样使用Python 3:
00000000 c2 80 c2 81 c2 82 c2 83 c2 84 c2 85 c2 86 c2 87 |................|
...
00000070 c2 b8 c2 b9 c2 ba c2 bb c2 bc c2 bd c2 be c2 bf |................|
00000080 c3 80 c3 81 c3 82 c3 83 c3 84 c3 85 c3 86 c3 87 |................|
...
000000f0 c3 b8 c3 b9 c3 ba c3 bb c3 bc c3 bd c3 be c3 bf |................|
总结:
- 一切从
0x80
到0xbf
已经0xc2
前缀。
- 从
0xc0
到0xff
的所有内容都将第6位设置为零,并且前置0xc3
。
那么,这是怎么回事?
在Python 2中,字符串是ASCII码,没有转换完成。告诉 在0-127 ASCII范围之外写一些东西,它说“okey-doke!”和 只是写这些字节。简单。
在Python 3中,字符串是Unicode。当写入非ASCII字符 时,它们必须以某种方式编码为。默认编码是UTF-8,编号为 。
那么,这些值如何以UTF-8编码?
码点从0x80
到0x7ff
编码如下:
110vvvvv 10vvvvvv
凡11个v
字符是码点的比特。
这样:
0x80 hex
1000 0000 8-bit binary
000 1000 0000 11-bit binary
00010 000000 divide into vvvvv vvvvvv
11000010 10000000 resulting UTF-8 octets in binary
0xc2 0x80 resulting UTF-8 octets in hex
0xc0 hex
1100 0000 8-bit binary
000 1100 0000 11-bit binary
00011 000000 divide into vvvvv vvvvvv
11000011 10000000 resulting UTF-8 octets in binary
0xc3 0x80 resulting UTF-8 octets in hex
所以这就是为什么你87
之前得到一个c2
。
如何在Python 3中避免这一切?使用bytes
类型。
还有其他的例子吗?你能找到一个模式吗? –