Unicode字符串的长度如何计算?

3
>>> c='中文'
>>> c
'\xe4\xb8\xad\xe6\x96\x87'
>>> len(c)
6
>>> cu=u'中文'
>>> cu
u'\u4e2d\u6587'
>>> len(cu)
2
>>> s=''
>>> s
'\xf0\xa4\xad\xa2'
>>> len(s)
4
>>> su=u''
>>> su
u'\U00024b62'
>>> len(su)
2
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> sys.stdout.encoding
'UTF-8'

首先,我想要澄清一些概念。我了解到像cu=u'中文'这样的Unicode字符串实际上是由Python shell默认编码为UTF-16的。对吗?所以,当我们看到'\u*'时,那实际上是UTF-16编码吗?而'\u4e2d\u6587'是一个Unicode字符串还是字节字符串?但是cu必须存储在内存中。

0100 1110 0010 1101 0110 0101 1000 0111

(将中文转换为二进制) 是 cu 保存的形式,如果是字节字符串吗?我说得对吗?

但它不能是字节字符串。否则 len(cu) 就不可能是2,应该是4!! 所以它必须是Unicode字符串。但是!!! 我也了解到

Python试图使用当前在sys.stdout.encoding中设置的任何编码方案隐式地对Unicode字符串进行编码,在此示例中为"UTF-8"。

>>> cu.encode('utf-8')
'\xe4\xb8\xad\xe6\x96\x87' 

那么!为什么len(cu)等于2?这是因为它里面有两个'\u'吗?

但这样len(su) == 2就没有意义了!

我有什么遗漏的地方吗?

我正在使用Python 2.7.12。


字符不等于字节。UTF16 字符是 2 个字节,但只算一个字符。 - Marc B
你首先想要了解Unicode。请参阅http://nedbatchelder.com/text/unipain.html。 - Martijn Pieters
@MartijnPieters 谢谢!非常有帮助。 - MMMMMCCLXXVII
@MarcB,您能提供更多详细信息吗? - MMMMMCCLXXVII
@MarcB,那么,len(ob)不仅仅是返回ob有多少字节,对吗? - MMMMMCCLXXVII
1个回答

0
Python的unicode类型保存着Unicode码位,而不是编码。Python内部如何实现这一点是一个实现细节,大多数情况下您不需要关心。它们不是UTF-16代码单元,因为UTF-16是另一种可以用来编码Unicode文本的编解码器,就像UTF-8一样。
最重要的是,标准的Python str对象保存着字节,这些字节可能包含经过某种编码的文本(您的示例使用了UTF-8,但这并不是必须的),而unicode则保存着Unicode码位。在交互式解释器会话中,您的终端编码决定了Python接收到的字节是什么(然后在创建u'...'unicode对象时,Python使用sys.stdin.encoding根据需要对其进行解码)。

只有在向sys.stdout(例如使用print)写入时,sys.stdout.encoding值才会发挥作用,Python将自动再次对您的Unicode字符串进行编码。只有在这种情况下,您的2个Unicode代码点才会被重新编码为UTF-8并写入您的终端,终端知道如何解释它们。

您可能想要了解有关Python和Unicode的更多信息,我推荐:


又有一个问题。正如你所提到的,只有在使用 print 时,Python 才会自动再次编码 Unicode 字符串。因此,当 Bash shell 接收到它以便在屏幕上显示并使用该 Unicode 匹配某些所谓的渲染或其他我不确定的东西时,它将再次对其进行解码,或者只是将其留给字形。那么,如果我想在屏幕上显示某些内容,我可以简单地认为 Unicode 是最后的形式吗?嗯,你能理解我的意思吗? - MMMMMCCLXXVII

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接