>>> 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,编码和解码可以缩小两个字符的宽度。
答案 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
中的代码点数。