首先,为什么要编码?
我们知道,计算机只能存储二进制串001100011....
如果要计算机存储一个数字7,计算机可以用00000111来表示
如果要存储'a'这个字符呢?肯定也用一个二进制串来表示字符a
这就是字符的编码,即将字符转化成二进制串的过程
那么相反的过程就是解码,即将二进制串转化为字符的过程
上面说到,用一个二进制串来表示字符a,那么具体用多少来表示a呢?
如果用01100001来表示字符a,这种映射方式就叫做ASIIC编码格式
ASIIC格式规定用一个字节来表示一个字符,也就是,最多之能表示256个字符
那么中文字符以及其他语言咋办呢?
unicode是另外一种编码方式,它规定最少用两个字节表示字符,也就是最少能表示65536个字符
这下,全世界语言是都能表示了
但是它在表示英文字母的时候也用两个字节,高字节都是00000000,显然很是浪费
于是出现了utf-8编码格式
它是对unicode的优化,对不同的情况进行了分类
如果是英文字母及常规符号用一个字节表示,中文字符用三个字节表示
可以发现,utf-8编码相对unicode编码在全是英文字符的情况下需要的二进制串可以减半
因此,在网络上传输或者文件存储的时候,都是用utf-8编码
python3中的str和bytes两种数据类型
python中的解码与编码分别由decode和encode两个模块实现
python(或者任何编程语言)中的编码如果没有指定编码格式的话,默认用的是unicode
因为任何运行在内存中的数据都是以unicode的方式编码的
此时如果对某个字符调用编码方法
则会返回该字符按照该编码格式对应的二进制结果,一般用十六进制显示
比如我在python中定义了变量a='a'
此时字符'a'在内存中是00000000 01010001,即0x61
执行a.encode()
返回值即是0x61
但对它进行unicode编码是没有意义的,为什么?
因为内存中本来存储的就是按照unicode编码的二进制串呀,这次编码操作只是为了用户查看它的编码结果而已
一般我们对一个字符编码无非是为了存储或者传输
而前面我们也了解了,unicode编码并不是存储和传输的最佳方式
一般我们会用utf-8进行编码
执行b=a.encode('utf-8')
则b为01010001,即0x61
将b存储到文件中,假设命名为test.txt
那么这个时候文件中的内容就是01010001,即0x61,就只有这么一个字节
也就是,下次你直接打开这个文件,并且读取文件中的内容
你会发现,得到的是完好无损的字符a
因为系统默认会对二进制串用unicode解码(任何加载到内存中的数据都是unicode格式)
而幸运的是对于字符a而言,unicode和utf-8两种格式的映射关系是一样的
如果保存的是中文字符,那么你大概率会得到一个乱码
那么如何得到正确的字符呢?
可以在读取的时候指定解码格式,比如
open("test.txt").read().decode("utf-8")
实际上,open("test.txt").read()的返回值是该字符按照该编码方式得到的二进制串
既然有二进制串这种数据,那么它肯定也属于某种数据类型
在python3中,我们把二进制串这种数据的类型称作bytes
而字符a的数据类型是str
str被编码后得到bytes,bytes是二进制串,能直接存储和传输
当然,如果直接打印bytes类型的数据的话,
我们也不会看到类似0101010001这样的结果,python会用0x61这样的十六进制表示方法来代替~