python3中关于编码那些事儿

Unicode和utf-8的编码问题在python3中显得更加突出。Python3新增了bytes类型,而string类型则默认用unicode编码。
从ASCII编码说起
计算机刚发明的时候,美国人的26个英文字母加上一些数字、标点符号、数学符号及其他特殊符号,用一个字节接可以全部编码完成,也就是从0000 0000到1111 1111,十进制是从0到255,一共可表示256个字符,每个字符一个字节。这个编码叫ASCII编码,是美国的国家标准编码。
但是,随着计算机的普及,世界上那么多国家、那么多语言,都要用ASCII来编码的话,显然是不够的,我国就提出过GB2312编码,用2个字节来编码一个汉字,后来在此基础上又扩展了GBK,GB13000.1,GB18030等编码。这还只是中国大陆简体字的编码,还有繁体字的BIG5编码,还有日本的SHIFT_JIS编码,韩国的Euc-kr编码,还有俄国的、阿拉伯的、西班牙的……
自然而然,人们就会想到一种通用编码,它可以包含世界上任何一种语言,给每一个语言中的每一个基本单位都分配唯一一个编码。这个通用的编码叫做Unicode编码,中文翻译为“统一码”
Unicode编码
Unicode一直在发展,最常用的是用两个字节表示一个字符,冷僻的用4个字节。这样,包括英语、汉语、日语、韩语在内的各种语言都可以用一个编码来表示了,看起来似乎问题已经解决了,但是事实是残酷的。每个字符都用2个字节编码,非英语国家的字符编码问题解决了,但是英语国家的人们就感觉吃亏了,因为原来只要用1个字节就能解决的事情现在要用2个字节了,这意味着在硬盘上存储时需要多一倍的存储空间,在网络上传输的时候也需要多一倍的存储空间,这么做太不划算了。因此,Unicode编码一出现便成为了一种理论上的编码,具体应用当中,它有着多种实现方式。其中,最常用的就是UTF-8编码。
UTF-8编码
【python3中关于编码那些事儿】UTF-8编码也称为一种“可变长”的编码 ,它的原理是这样:根据各语言对应的数字不同分别用不同的字节去存储,英文字母用1个字节编码,中文用3个字节编码,生僻字符用4-6个字符编码。这样一来,ASCII编码就无痛融入了UTF-8编码之中,解决了英语国家存储空间多一倍的问题。
编码转换
在计算机内存中,统一使用Unicode编码,当保存到硬盘中或者在网络上传输的时候,可以有不同的编码方式,比如英语国家可以编码成ASCII格式,非英语国家可以编码成本国自制的格式(如我国的GB2312码)
反过来,计算机硬盘上的文本或网络上传输的文本可能有不同的编码方式,但是要在计算机内存中操作就要把它们转换成Unicode编码进行处理,保存时,又可以选择不同的编码方式进行编码。
把Unicode比作一个人,他在不同的国家可能有不同的名字,但是这个人始终是这个人。
Python3.X的str和bytes
python3中的字符串默认是以Unicode编码的,这意味着

中国='china'

这样的格式也是允许的。
在Python3中,如果我们创建了一个字符串,它默认的编码就是Unicode,如果想要保存在硬盘中或者在网络上传输,就要把它编码成bytes格式,我们可以利用Python3自带的str.encode(‘utf-8’)方法将字符串str编码成utf-8格式,当然你也可以编码成gb2312、gbk格式。
反过来,如果我们打开一个文本文件,我们读到的数据是bytes格式,它可能是任何编码,我们就需要指定以何种编码打开,这个过程我们成为解码。通常我们用utf-8格式来解码,利用pyhotn3自带的bytes().decode(‘utf-8’)方法。
字符数量
  • Unicode编码中,以字符为单位,计数的时候一个字符就是1,len(’中国’)=2,len(‘abc’)=3。
  • utf-8编码中,以字节为单位,计数的时候取决于字符所占的字节数,len(‘中国’)=6,len(‘abc’)=3

    推荐阅读