python 字符编码
一.字符编码
计算机中,数据的存储和运算都要使用二进制(因为计算机用高、低电平分别表示1和0),那么就需要一个标准,将数据转为二进制表示
ASCII码就是一套标准,但是ASCII只支持字母和字符的转化,因为ASCII码是美国人提出来的,那么中文,韩文,日文怎样转为二进制呢?中国人规定了自己的标准gb2312编码;日本人规定了自己的Shift_JIS编码;韩国人规定了自己的Euc-kr编码,可是如果一篇文档上这三个国家的语言都出现了,该用哪一个标准呢?unicode应运而生
ASCII码用1个字节代表一个字符
unicode常用两个字节代表一个字符,生僻字需要4个字节
这时候乱码问题消失了,所有的文档我们都使用unicode,但是新问题出现了,如果我们的文档通篇都是英文,用unicode会比ascii耗费多一倍的空间,在存储和传输上十分的低效
本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8
编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间
二.编码对应过程
内存中的编码固定使用unicode,唯一可变的是硬盘上对应的字符编码
1、在存入磁盘时,需要将unicode转成一种更为精准的格式,utf-8将数据量控制到最精简
2、在读入内存时,需要将utf-8转成unicode
所以我们需要明确:内存中用unicode是为了兼容万国软件,即便是硬盘中有各国编码编写的软件,unicode也有相对应的映射关系,但在现在的开发中,程序员普遍使用utf-8编码了,估计在将来的某一天等所有老的软件都淘汰掉了情况下,就可以变成:内存utf-8<->硬盘utf-8的形式了
三.乱码问题
原因:
1.存文件的时候出现乱码
文件中有各个国家的文字,存的时候以shiftjis编码去存,那么不是日文的文字就会保存失败,使用shiftjis编码打开时,只有日文能显示,其他会报错
2.存文件的时候正常,读文件的时候乱码
存文件时用utf-8编码,保证兼容万国,不会乱码,而读文件时选择了错误的解码方式,比如gbk,则在读阶段发生乱码,读阶段发生乱码是可以解决的,选对正确的解码方式就ok了
解决办法:
1、保证不乱吗的核心法则就是,字符按照什么标准而编码的,就要按照什么标准解码,此处的标准指的就是字符编码
2、在内存中写的所有字符,一视同仁,都是unicode编码,比如我们打开编辑器,输入一个“你”,我们并不能说“你”就是一个汉字,此时它仅仅只是一个符号,该符号可能很多国家都在使用,根据我们使用的输入法不同这个字的样式可能也不太一样。只有在我们往硬盘保存或者基于网络传输时,才能确定”你“到底是一个汉字,还是一个日本字,这就是unicode转换成其他编码格式的过程了
四.应用
执行程序的三个阶段
python a.py (第一步将文件内容读入到内存中)
阶段一:启动python解释器
阶段二:python解释器此时就是一个文本编辑器,负责打开文件a.py,即从硬盘中读取a.py的内容到内存中
需要在python文件开头指定用什么格式读入内存
例如:#coding:utf-8
阶段三:读取已经加载到内存的代码(unicode模式),然后执行,执行过程中可能会开辟新的内存空间
但是程序在执行过程中,会申请内存(与程序代码所存在的内存是俩个空间)用来存放python的数据类型的值,而python的字符串类型又涉及到了字符的概念 比如x="hello",会被python解释器识别为字符串,会申请内存空间来存放字符串类型的值,至于该字符串类型的值被识别成何种编码存放,这就与python解释器的有关了,而python2与python3的字符串类型又有所不同。
五.python2和python3字符串类型的区别
1.python2中有的两种字符串类型是str和unicode
假设 #coding:gbk
str1 = '你好' (str类型)
str2 = u'你好' (unicode类型)
str2 = str1.decode('gbk')
在终端打印的时候也需要与终端的编码格式一致,在本例中,使用str类型时,如果终端编码为gbk则可以正常显示,如果终端为其他编码则显示会乱码
对于unicode格式的数据来说,怎么打印都不会乱码
2.在python3 中也有两种字符串类型str和bytes
str就是unicode
假设 #coding:gbk
str1 = '你好' (str类型) #程序执行时,无需加上u,'你好'也会被以unicode形式保存新的内存空间中
而在python3是bytes类型,在python2中则是str类型