Unicode编码

为了介绍Python的编码知识,我们先来回顾下计算机发展历史上文字是如何编码的。

计算机在美国被发明之后,一开始需要被存储的字符个数不多,包括大小写的英语字母以及常用的标点符号,在7个bit内就能把所有的适用于美国当时要求的字符给枚举出来,这就是ASCII码,是American Standard Code for Information Interchange的首字母缩写。

计算机继续推广后,在文字记录上首先遇到的问题就是即使是跟英语相近的语言,比如法语等,它们有很多的字母需要在正常的字母上方加上比如冒号等符号,例如éÍ ,那7个bit就不够用了。于是各个语言就开始在ASCII的基础上扩充,扩充到了一个字节,也就是8个bit。法语加上法语自己的一些特殊字母成了一个新的编码集,俄语加上自己的西里尔字母也成了一个新的编码集。这些尝试在自己语言内部是没有问题,但是一个文档中需要混合两种以上的语言时候,就出现错误了,没有一个编码集能够覆盖全部语言。

这就是后来为什么又把编码扩充到了两个字节,或者16个bit的原因,用一个超大的编码集把所有的文字都包含进来,这种努力直到字符集的长度变为了21个bit,也就是字符编码的范围从00x10FFFF,才真正的把世界上所有的文字都囊括进去了。最后的这个编码标准,就是ISO 10646,或者也可以说是Unicode

回顾完了历史,我们来看什么是UTF-8。现有的ISO10646解决了编码的终极问题,任何字符都可以在这个编码集中找到自己的位置,但是如果我们用这种方法来存储文字的话,就会有一个问题了,太浪费空间。因为常用的字符都可以在8个比特或者16个比特内找到自己的位置,假如我们都有21个比特来存储字符的话,效率大概只有30%-50%,所有就出现了类似UTF-8这样的编码,它也是现行被采用最多的编码方式。

UTF-8UTF的意思是Unicode Transformation Format-Unicode转换格式,8的意思是8比特编码。它的规则如下,

  1. 假如编码数字<128,就采用用相应的编码值。
  2. 假如编码数字>128,就分别用2、3或4个字节来表示,其中每个字节的取值范围在128-255,也即是最高位都为1,是为了跟ASCII区分开,ASCII的字节最高位bit是0

Python 3以后,字符串存储都是以unicode的方式来存储了,而不像Python 2中那样字符串是默认以bytes来存储的。

# Python 3
type("f") == type(u"f")  # True, <class 'str'>
type(b"f")               # <class 'bytes'>

# Python 2
type("f") == type(b"f")  # True, <type 'str'>
type(u"f")               # <type 'unicode'>