“字符串”是个相当简单的概念:一个字符串是一个字符序列。问题出在“字符”的定义上。

在 2015 年,“字符”的最佳定义是 Unicode 字符。因此,从 Python 3 的 str 对象中获取的元素是 Unicode 字符,这相当于从 Python 2 的 unicode 对象中获取的元素,而不是从 Python 2 的 str 对象中获取的原始字节序列。

Unicode 标准把字符的标识和具体的字节表述进行了如下的明确区分。

把码位转换成字节序列的过程是编码;把字节序列转换成码位的过程是解码。示例 4-1 阐释了这一区分。

示例 4-1 编码和解码

>>> s = 'café'
>>> len(s)  # ➊
4
>>> b = s.encode('utf8')  # ➋
>>> b
b'caf\xc3\xa9'  # ➌
>>> len(b)  # ➍
5
>>> b.decode('utf8')  # ➎
'café

'café' 字符串有 4 个 Unicode 字符。

❷ 使用 UTF-8 把 str 对象编码成 bytes 对象。

bytes 字面量以 b 开头。

❹ 字节序列 b 有 5 个字节(在 UTF-8 中,“é”的码位编码成两个字节)。

❺ 使用 UTF-8 把 bytes 对象解码成 str 对象。

 如果想帮助自己记住 .decode().encode() 的区别,可以把字节序列想成晦涩难懂的机器磁芯转储,把 Unicode 字符串想成“人类可读”的文本。那么,把字节序列变成人类可读的文本字符串就是解码,而把字符串变成用于存储或传输的字节序列就是编码

虽然 Python 3 的 str 类型基本相当于 Python 2 的 unicode 类型,只不过是换了个新名称,但是 Python 3 的 bytes 类型却不是把 str 类型换个名称那么简单,而且还有关系紧密的 bytearray 类型。因此,在讨论编码和解码的问题之前,有必要先来介绍一下二进制序列类型。