人类使用文本,计算机使用字节序列。 Python 3 明确区分了人类可读的文本字符串和原始的字节序列。 隐式地把字节序列转换成 Unicode 文本已成过去。

一个字符串是一个字符序列。字符的最佳定义是 Unicode 字符。从 Python 3 的 str 对象中获取的元素是 Unicode 字符,这相当于从 Python 2 的 unicode 对象中获取的元素,而不是从 Python 2 的 str 对象中获取的原始字节序列。

二进制序列类型特点:

  • Python 3 引入的不可变 bytes 类型和 Python 2.6 添加的可变 bytearray 类型。
  • 二进制序列类型在很多方面与 Python 2 的 str 类型不同
  • bytes 或 bytearray 对象的各个元素是介于 0~255(含)之间的整数,而不像 Python 2 的 str 对象那样是单个的字符。(称为字节序列的原因,每个元素一个字节)
  • 二进制序列其实本质上是整数序列,但字面量表示后其中有 ASCII 文本等

虽然二进制序列其实是整数序列,但是它们的字面量表示法表明其中有 ASCII 文本。各个字节的值可能会使用下列三种不同的方式显示:

  • 可打印的 ASCII 范围内的字节(从空格到 ~),使用 ASCII 字符本身。
  • 制表符、换行符、回车符和 \ 对应的字节,使用转义序列 \t、\n、\r 和 \\
  • 其他字节的值,使用十六进制转义序列(例如,\x00 是空字节)。

Unicode标准中字符的标识字符的具体表述

  • 字符的标识,即码位,是 0~1 114 111的数字(十进制),在 Unicode 标准中以 4~6 个十六进制数字表示,而且加前缀“U+”。
  • 字符的具体表述取决于所用的编码。编码是在码位和字节序列之间转换时使用的算法。在 UTF-8 编码中,A(U+0041)的码位编码成单个字节 \x41,而在 UTF-16LE 编码中编码成两个字节 \x41\x00。

把码位转换成字节序列的过程是编码;把字节序列转换成码位的过程是解码。

示例1:

>>> s = 'café'
>>> len(s)
4
>>> b = s.encode('utf8')
>>> b
b'caf\xc3\xa9'
>>> len(b)
5
>>> b.decode('utf8')
'café'

示例1说明: ‘café’有4个Unicode字符。 使用 UTF-8 把 str 对象编码成 bytes 对象。bytes 字面量以 b 开头。 字节序列 b 有 5 个字节(在 UTF-8 中,“é”的码位编码成两个字节)。 b’caf\xc3\xa9’前 3 个字节 b’caf’ 在可打印的 ASCII 范围内,后两字节则不然。 最后使用 UTF-8 把 bytes 对象解码成 str 对象。

示例2:

>>> s = '中国'
>>> len(s)
2
>>> b = s.encode('utf8')
>>> b
b'\xe4\xb8\xad\xe5\x9b\xbd'
>>> len(b)
6
>>> b.decode('utf8')
'中国'

示例2跟示例1类似,只不过“中”和“国”在UTF-8中分别编码成三个字节。

参考《流畅的Python》第4章内容。