[知识总结]python编码详解(Python)

1.认识编码:

要想搞懂python中的编码问题,首先要了解什么是编码,由于计算机的组成与设计原理导致计算机只能储存和处理二进制数据,无论是在屏幕上显示的文字、图像等,硬盘里存储的文件、程序等,内存里存储的临时数据等,他们本质都是以二进制的方式储存在计算机中的。

你可以想象硬盘中存储着一个txt文本文档,这个文本文档在硬盘上存储的是01010101...一连串二进制数字,当你在操作系统的UI界面双击它时,计算机会先到硬盘中找到这一堆二进制数字,然后将这堆数字加载到内存中,之后操作系统会在内存中读取这堆数字然后通过输出设备(显示器)输出,把这堆数字显示在你眼前。

这时候有人就会问了,不对啊,它显示的是一堆二进制数字啊,可我想看的是文字啊。确实,显示器上显示的确实不是保存在硬盘上的二进制数据,这是因为操作系统先将这些二进制数字转化成了你所认识的文字,然后再显示给你看。

那么,操作系统是怎么将这些二进制数字转化成文字的呢?

首先,对于一连串二进制数字,我们规定每8个二进制就是一个字节,通过排列组合知识,我们可以知道每个字节有2^8次方种组成方式,换算成十进制就是说,一个字节长度的二进制数据可以表达2^8=256种不同的信息。我们可以将这256种组成方式,每种对应一个文字,比如我可以让01000001的二进制数字代表大写字母A。

这时候,当操作系统以每8个二进制数字为一组的规则去解读硬盘上的二进制数字的时候,当有一组数字是01000001时,操作系统就在屏幕上显示大学字母A。

这就是编码的基本原理:将不同的二进制数字与不同的文字符号做一个绑定

以上我举的例子:让01000001的二进制数字代表大写字母A,其实就是ASCII码(American Standard Code for Information Interchange,美国信息交换标准代码) 这种字符编码中的捆绑关系。

其实每个人都可以按照自己的喜好去规定哪个二进制数字代表哪个字符,但为了能够在互相通信中不造成混乱,大家就要使用相同的编码方式。

上面我们说8个二进制数字是一个字节,但是一个字节最多只能代表256种不同的字符,那么如果我要编码中文怎么办?明显中文不只256个汉字。很简单,我们可以规定两个字节即16个二进制数字为一组,每一组16个二进制数字代表一个汉字,这样最多可以表示2^16=65536个汉字,远远能满足需求了。举个例子1011000010100001这个二进制数字代表汉字‘啊’,这就是GBK(全称《汉字内码扩展规范》)所规定的捆绑关系。

那么有人就又问了,我刚才说为了通信不造成混乱,那么应该只有一个通用的编码方式啊,为什么还会有我上面举的例子ASCII、GBK这些。

其实全球通用的编码方式是存在的,叫Unicode(统一码,万国码),Unicode规定所有的字符都用两个字节(16个二进制数字组合)表示,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。在Unicode中,无论你是英语、汉语、韩语、日语等任何语言,都能够在其中找到本国语言文字对应的二进制数字。这样如果全球都使用Unicode,那么我在硬盘上保存的汉字(一堆按Unicode规则排列的二进制数字),到全球任何一台电脑上也能正常显示(他们只需按Unicode的规则解析这些二进制数字即可)。

这很好,但是美国人不高兴了,ASCII码就是美国人搞出来的,它只支持英语和一些特殊字符,不支持中文或其他语言,但ASCII有一个好处,一个英文字符只占一个字节,而如果美国人使用Unicode的话,一个英文字符就要占两个字节,这就凭空增大了数据的体积。比如一个美国人写了一部非常长的小说,用ASCII的编码方式存在硬盘里只要1个G的空间,用Unicode就要2个G,这对于英文数据的存储和通信造成了极大的资源浪费。

所以后面又出现了UTF-8编码,UTF-8在Unicode的基础上优化了一下,英文字符只占一个一节,其他语言字符是情况占不同的字节。但是美国人会不高兴,其他国家的人也会因为各种原因想用自己的编码。

比如在UTF-8中,中文占3个字节,所以国内大多数计算机上的默认编码方式还是gbk,

总之,各种各样的原因导致了现在世界上还依然存在着不同的编码,所以,在用python编程的时候,就需要我们搞清楚对于不同编码间的转换。

2.python工作机制:

python文本编辑器(编写python程序时用的各种IDE或文本编辑器)运行原理:文本编辑器打开后,等待你输入代码。当你开始输入代码的时候,其实你是在编写一个字符串,当你编写完毕,准备保存的时候,如果你在文件前两行写上了#-*-coding:utf-8-*-,就按照你声明的编码方式去将你写的字符串编码成二进制数据,如果没有声明,就用默认的编码方式(python2是ASCII,python3是UTF-8)去编码,编码完成后将数据保存在硬盘上。

python解释器运行原理:读取硬盘上保存的.py源文件(实际为一堆二进制数字),按照解释器默认的编码方式(python2是ASCII,python3是UTF-8)将二进制数据解码,即解释器按照相应的编码规则去理解这堆二进制数字,抽象上得到了一组字符串(如果文件头通过#-*-coding:utf-8-*-语句声明了编码方式,就用声明的编码方式解码,这里这句语句声明了编码方式是UTF-8)。然后,需要注意的是,接下来的过程python2和python3有所不同。

在python2中,会直接对这组抽象上的字符串进行关键字分析(语法分析),比如遇见‘print(‘你好!’)’,会调用print函数打印‘你好!’,所以在python2中字符串str=二进制bytes。

而在python3中,会先将抽象上的字符串按照Unicode规则编码一次,得到Unicode格式的二进制数字,再按照unicode的规则去理解,进行语法分析并执行,所以在python3中字符串str和二进制bytes不同,python3中str都是unicode类型的而不是bytes类型的。

3.乱码原因:

python2中,默认的编码方式是ASCII,如果你想你让python程序源文件支持中文,你需要在源文件前两行加上#-*-coding:utf-8-*-这样的声明,这样python的解释器在读取运行你的源文件的时候,会采用你声明的编码方式去解析你存在硬盘上的数据(一堆二进制数字)。如果硬盘上存储的二进制数据是按照gbk格式编码的,即每2个字节(16个二进制数字)代表一个汉字,你却用UTF-8的规则去解析,那么显示就会乱码。

打个比方:硬盘上存储了10110000101000011011000010100001这么一组数字,共32个数字,他是‘啊啊’这两个字按照GBK的编码方式转换成的二进制数字。这时候如果你用UTF-8分规则去解析它,就会发生错误,因为UTF-8中中文字符占3个字节,即24个二进制数字,多余的8个数字就无法解析,并且已经解析的24个数字明显也不会得到‘啊啊’这两个汉字。

所以,出现乱码的根本原因还是解码选择的编码方式和编码选择的编码方式不同而导致的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值