python3中有两种表示字符序列的类型:bytes和str。前者包含原始的8位值,后者实例包含的是unicode。
8位值指的就是在某种编码下的一个字节,比如'A'用ascii编码对应的值就是65,对应的二进制表示为01000001,那么'A'如果用ascii编码为bytes类型的话,它所包含的原始8位值就是01000001。
unicode则是为了统一各种语言编码而产生的一套统一的编码方式,任何语言都可以编码为unicode,在计算机的内存中,也只有unicode。在计算机最早期,只有ascii编码,但是ascii编码方式一个字符只占用一个字节,这样就只能表示英文字符了,这时候中文字符就无法表示了,所以我国出现了gb2312的编码方式,使得中文可以表示,各个国家有着各个国家的语言,如果每个语言都是用一套各自的编码方式,那这个就没有办法统一了,别人写的代码可能换个语言环境就无法正常运行了,因此才出现了unicode,统一了各种编码方式,即是所以得语言都可以通过unicode进行编码,这时候unicode就不可能像ascii那样只占用1个字节了,因为一个字节意味着最多只能表示256个字符,所以语言的字符数肯定不止256,通常来讲unicode占用2个字节。
那么utf-8又是什么呢?utf-8的产生是为了节省空间而出现的,前面讲到unicode通常占用2个字节,但是对于英文字符其实只需要一个字节就可以表示了,因此utf-8为了节省空间实现了动态长度的表示,比如它在编码中对英文字符用1个字节表示,而通常对于汉字就是用3个字节表示。
为了验证前面讲到的,我们可以做个试验验证一下:
可以看到'A'的ascii编码是65,转成二进制就是0b1000001,unicode编码和utf-8编码均为65,二进制0b1000001。
汉字‘中’无法用ascii编码,如果我们执行'中'.encode('ascii')会报错,它的unicode编码是'\u4e2d',转成二进制是01001110 00101101,utf-8编码是\xe4\xb8\xad,转成二进制是11100100 10111000 10101101。
一般情况下没有特殊业务需求,我们尽量使用utf-8编码即可。例如平常我们用notepad++存文本文件的时候,会保存为utf-8无bom的编码,意味着这个文本文件是通过utf-8编码后存储了,例如对于汉字’中‘在文本文件中就会存为二进制的11100100 10111000 10101101,那么当我们读取这个文本文件到内存中时就必须把它转为unicode读入到内存了,因为实际上计算机的内存中只存在unicode,这就是为什么我们在写python的时候常常在文件的顶部加一行# -- coding: utf-8 --,这一句就告诉解释器以utf-8的编码方式去读取这个文件。