在python3中编码,字符长度和显示宽度

时间:2014-04-27 13:35:44

标签: python-3.x

>>> line="你好".encode("gbk").rjust(10)
>>> print(line)
b'      \xc4\xe3\xba\xc3'
>>> print(line.decode("gbk"))
      你好
>>> print("你好".rjust(10))
        你好
>>> len("你好".rjust(10))
10
>>> len(line.decode("gbk"))
8
>>> len("你好".encode("gbk").rjust(10).decode("gbk"))
8

很奇怪len(“你好”.rjust(10))= 10,len(“你好”.encode(“gbk”)。rjust(10).decode(“gbk”))= 8,编码和解码可以缩小两个字符的宽度。

1 个答案:

答案 0 :(得分:1)

您看到的是字节和代码点之间的差异。当您获取len对象的bytes时,您将获得字节数。当您获取len对象的str时,您将获得unicode代码点的数量。

line是一个字节对象,由10个字节组成:

>>> line
b'      \xc4\xe3\xba\xc3'
>>> list(line)
[32, 32, 32, 32, 32, 32, 196, 227, 186, 195]
>>> len(line)
10

bytes解码为str时,str由8个代码点组成:

>>> line.decode("gbk")
'      你好'
>>> list(line.decode("gbk"))
[' ', ' ', ' ', ' ', ' ', ' ', '你', '好']

>>> len(line.decode("gbk"))
8

两个字节b'\xc4\xe3'被解码为一个代码点:

>>> b'\xc4\xe3'.decode('gbk')
'你'

同样适用于b'\xba\xc3'


请注意,代码点与字符不完全相同。代码点可能是组合重音符号,例如:

>>> print(u'a\u0300')
à
>>> len(u'a\u0300')
2

某些组合标记can be composed与另一个代码点组成一个代码点。实际上,上述例子就是这种情况:

>>> import unicodedata as UD
>>> UD.normalize('NFKC', 'a\u0300')
'à'
>>> len(UD.normalize('NFKC', 'a\u0300'))
1

然而,并非所有组合标记都如此组合:

>>> UD.normalize('NFKC', 'a\u030b')
'a̋'
>>> len(UD.normalize('NFKC', 'a\u030b'))
2

因此,即使您进行了规范化,也不能假设您看到的字符数是str中的代码点数。