编码的秘密(python版)
编码(python版)
最近在学习python的过程中,被不同的编码搞得有点晕,于是看了前人的留下的文档,加上自己的理解,准备写下来,分享给正在为编码苦苦了挣扎的你。
编码的概念
编码就是将信息从一种格式转换成另一种格式,计算机只认识二进制,简单的理解,将我们眼睛看到的文字转换为计算机能够识别的二进制格式视为编码,而二进制以某种编码格式转换为我们能看的文字的过程可以看成是解码。既然计算机只能认识二进制0,1,那么我们用的字母、数字和文字等是怎样和他们对应的呢?那就请继续看吧!
python中查看默认的编码规范是:
- import sys
- print(sys.getdefaultencoding())
- #运行结果:
- utf-8
ASCⅡ码
我们都知道计算机是米国发明的,起初的时候也只有米国那些国家使用,而他们的语言仅仅只有26个字母组成,再加上一些符号,所以在一开始的时候,用的编码规则就是ASCⅡ码。ASCⅡ,中文名叫美国信息交换标准代码,因为名叫American Standard Code for Information Interchange,下面我们来看看ASCⅡ表:
ASCⅡ码用一个字节,也就是8位二进制组来标识一个字符,比如00100001就代表字符!,第一版的ASCⅡ没有用到最高的一个bit,所以取值范围为0-127,只能表示128字符。为了满足西欧等国家的字符要求,于是用上了最高位的bit,能表示的字符也从128增加到了256个。
在python中使用函数ord(),可以字符转换为对应数值,使用函数chr可以将数值转换为对应字符:
- >>> ord("a") #将字符转换为数值
- >>> ord("A")
- >>> chr()
- 'A'
- >>> chr() #将数值转换为字符
- 'a'
- >>>
GB2312和GBK
当计算机漂洋过海来到了中国,ASCⅡ已经不能满足我大天朝的需求了,常用的汉字大致都有2k-3k。所以中国国家标准总局在1980发布了《信息交换用汉字编码字符集》,也就是GB2313标准。GB2312一共收录了7445个字符(6763个汉字和682个其他符号),包括拉丁字母、希腊字母和日文平假名等,基本上满足了国人的需求。
在GB2312中每个汉字使用两个字节来表示,分为高字节和低字节,汉字区高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768,其中有5个空位是D7FA-D7FE,规定第一个字节大于127的就代表这是一个汉字的开始(这一个字节和下一个字节就代表一个汉字),每个字节的最高位都位1。
但是对于人名、古汉语等方面出现的罕用字,GB2312不能处理,后来就出现了GBK。GBK向下兼容GB2312,其编码范围从8140到FEFE(不包括xx7F),共23940个码位,共收录了21003个汉字,这还是很厉害的了。现在我们使用的计算机默认的就是GBK编码。
Unicode和UTF-8
我们国家搞出了GBK,其他的国家也搞出了各种各样的编码,比如小日本的SJIJ,宝岛台湾的BIG5,国际组织一看,这不行啊,每个地方都各自搞各自的,那么在不同的国家之间就会出现不兼容,我用GBK编码格式写的软件,弄到你编码格式为SJIJ的计算机就不能执行了。所以就出现了Unicode,也称万国码。unicode是用2个字节来表示一个字符的,65536类个字符,这足以覆盖世界上所有的文字。
这样虽好,但是美国人民就不开心了,我一个字母,比如'a'就需要占用一个字节,现在需要占用两个字节,这样就大大的浪费了内存和硬盘的空间,所有后来就出现了UTF-32,UTF-16和UTF-8,前两个这里就不在敖述了,现在并不常用,我们这看看这个UTF-8,UTF-8是一种可变长的编码格式,存储英文字母只需要一个字节,存储汉字需要3个字节,但超大字符集中的更大多数汉字要占4个字节。我们在内存里面的数据是unicode,在传输数据和保存数据的时候使用UTF-8已节省空间和带宽。
Python2的编码
在python2中默认的编码是ASCII,python2的字符串类型有两种:str和Unicode,这两个只是字符串类型的名字,我们主要看它们在内存里面的内存地址:
- #coding=utf8
- name = '彬彬'
- name2 = u'彬彬' #加u,将字符串类型改为Unicode
- print repr(name)
- print repr(name2)
- #输出结果
'\xe5\xbd\xac\xe5\xbd\xac' #字节数据
u'\u5f6c\u5f6c' #Unicode数据
在python2中,str类型字符串类型在内存中存储的是bytes数据,Unicode类型字符串在内存中存储的是unicode数据。那两种数据之间是什么关系了?这里就涉及到了解码(encode)和编码(decode)了。
- #coding=utf8
- name = '彬彬' #name为字节数据类型
- name2 = u'彬彬' #name为unicode数据类型
- print repr(name)
- print repr(name2)
- name3 = name.decode('utf8')
- print type(name3)
- print repr(name3)
- name4 = name2.encode('utf8')
- print type(name4)
- print repr(name4)
- #运行结果
- '\xe5\xbd\xac\xe5\xbd\xac'
- u'\u5f6c\u5f6c'
- <type 'unicode'>
- u'\u5f6c\u5f6c'
- <type 'str'>
- '\xe5\xbd\xac\xe5\xbd\xac'
由上运行结果可知,unicode转换为bytes数据的过程是编码。从bytes数据转换为unicode数据的过程是解码。我们再来看一下:
- #coding=utf8
- name = '彬彬'
- name3 = name.decode('big5')
- print name3
- #运行结果
- 敶砍蓮
我们可以看到得到一堆乱文,name存在内存里的时候是以UTF编码成的bytes数据,而我们这里decode('big5')使用big5来解码,虽然成功了,但是输出结果却不是我们想要的结果。
当我们把第一行coding改为big5的时候就不会出现乱文了,
- #coding=big5
- name = '彬彬'
- name3 = name.decode('big5')
- print name3
- #运行结果
- 彬彬
所以我们用什么规则编码的就要用什么区解码!
注意:我们在终端显示出来的明文,就是你用户所看到的,其实都是已经转换成unicode到内存里面,而bytes数据一般都是计算机识别的。
Python3的编码
在Python3中也定义了2种类型的字符串类型,str和bytes,str类型存储unicode数据,bytes类型存储bytes数据。
- name = "彬彬"
- name2 = b"hello"
- print(type(name))
- print(type(name.encode('utf8')))
- print(type(name.encode('gbk')))
- print(type(name2))
- print(type(name2.decode('utf8')))
- #运行结果
- <class 'str'>
- <class 'bytes'>
- <class 'bytes'>
- <class 'bytes'>
- <class 'str'>
如上运行结果,bytes转换为unicode为解码,uicode转为bytes数据类型为编码。
由上图所示,在不同的编码之间转换的时候,我们都要经过unicode这个中转站,没办法,虽然unicode老大哥强大呢,当我们想把utf-8编码的数据转换为gbk的,我们就需要把utf-8的数据先解码成unicode,再由unicode编码成gbk。
在py2和py3中有个重要的区分就是,py2会自动把bytes数据解码成unicode,而py3就不会自动把bytes解码成unicode了。所以说py3更清晰的区分了bytes数据和unicode。
- #py2中
- print(u"liu" + "bin")
- #运行结果
- liubin
- #py3中
- print("liu" + b"bin")
- #运行结果
- Traceback (most recent call last):
- File "E:/py/字符编码2.py", line 2, in <module>
- print("liu" + b"bin")
- TypeError: Can't convert 'bytes' object to str implicitly
- print("liu" + (b"bin").decode('utf8'))
- #运行结果
liubin
一个.py文件的"一生"
那我们创建.py文件,到执行.py文件,这里面的编码和解码是怎么来的呢?
1.当我们创建一个.py文件的时候,会有一个默认的编码格式(这里以pycharm为例),在右下角,默认是UTF-8,当然你也可以选择其他的编码:
2.当我们在.py文件里面写入代码的时候,会以unicode的编码格式保存在内存中;
- print("你好,世界!")
3.当我们保存的时候,会将Unicode数据编码成utf-8格式的数据,然后保存在硬盘里面;
4.当我们执行文件的时候,pycharm会调用python的解释器来读取文件,在py2中,默认会以ASCII将代码解码成unicode数据,但是ASCII码并不认识中文,所以就会出现报错。
- File "E:/py/�ַ�����.py", line 2
- SyntaxError: Non-ASCII character '\xe4' in file E:/py/�ַ�����.py on line 2, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
所以,在py2中,我们需要加上:
- #coding=utf8
- print("你好,世界!")
- #运行结果
- 你好,世界!
但是在py3中就不存在这个问题了,只要编码的时候适用的是UTF-8,python3默认的编码规范就是UTF-8,它会用UTF-8来将UTF-8的bytes数据解码成unicode,然后在计算机终端显示!
编码的秘密(python版)的更多相关文章
- python之simplejson,Python版的简单、 快速、 可扩展 JSON 编码器/解码器
python之simplejson,Python版的简单. 快速. 可扩展 JSON 编码器/解码器 simplejson Python版的简单. 快速. 可扩展 JSON 编码器/解码器 编码基本的 ...
- python版 百度签到
经常玩贴吧,刚学python ,所以自己弄了一个python版的签到程序.自己的东西总是最好的. 登陆模块参考的http://www.crifan.com/emulate_login_website_ ...
- 自己动手实现智能家居之树莓派GPIO简介(Python版)
[前言] 一个热爱技术的人一定向往有一个科技感十足的环境吧,那何不亲自实践一下属于技术人的座右铭:“技术改变世界”. 就让我们一步步动手搭建一个属于自己的“智能家居平台”吧(不要对这个名词抬杠啦,技术 ...
- 【数据结构与算法Python版学习笔记】引言
学习来源 北京大学-数据结构与算法Python版 目标 了解计算机科学.程序设计和问题解决的基本概念 计算机科学是对问题本身.问题的解决.以及问题求解过程中得出的解决方案的研究.面对一 个特定问题,计 ...
- 【原】Learning Spark (Python版) 学习笔记(三)----工作原理、调优与Spark SQL
周末的任务是更新Learning Spark系列第三篇,以为自己写不完了,但为了改正拖延症,还是得完成给自己定的任务啊 = =.这三章主要讲Spark的运行过程(本地+集群),性能调优以及Spark ...
- 数据结构:顺序表(python版)
顺序表python版的实现(部分功能未实现) #!/usr/bin/env python # -*- coding:utf-8 -*- class SeqList(object): def __ini ...
- python版恶俗古风自动生成器.py
python版恶俗古风自动生成器.py """ python版恶俗古风自动生成器.py 模仿自: http://www.jianshu.com/p/f893291674c ...
- LAMP一键安装包(Python版)
去年有出一个python整的LAMP自动安装,不过比较傻,直接调用的yum 去安装了XXX...不过这次一样有用shell..我也想如何不调用shell 来弄一个LAMP自动安装部署啥啥的..不过尼玛 ...
- Zabbix 微信报警Python版(带监控项波动图片)
#!/usr/bin/python # -*- coding: UTF- -*- #Function: 微信报警python版(带波动图) #Environment: python import ur ...
随机推荐
- jquery分页插件的修改
前言 最近分页功能使用的比较多,所以从网上下载个jquery分页插件来使用, 之前用的都挺好的,直到昨天出现了逻辑问题,反复查看自己的代码,最后发现是点击页码后执行了多个点击事件.最后只有自己查看源码 ...
- python——网络编程
Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...
- DFB系列 之 Flip()更新buffe
1. 函数原型解析 函数声明: DFBResult Flip ( IDirectFBSurface * thiz, const DFBRegion * region, ...
- cas错误:org.jasig.cas.client.validation.TicketValidationException: No principal was found in the response from the CAS server.
这个问题困扰了我好几天,最终被这个哥们解决了,具体请参考:http://www.oschina.net/question/252484_149958?sort=time
- mui开发app之联网应用传输数据
手机的app分为,在线和单机,在线就是类似于C/S模式,能与服务器与他人共享数据的程序,单机就是在没有网络下可以玩转的app. 目前互联网盛行的时代,99%的程序都是联网环境下工作的.那么如何开发本地 ...
- windows下nodejs安装及配置
1)在 http://nodejs.org/download/下载一个window的安装包 2)运行安装包,设置安装路径,如安装到D:\nodejs,安装后会自动将d:\nodejs添加到系统变量pa ...
- 让div自适应浏览器窗口居中显示
今天做 banner 时发现一个问题,就是浏览器窗口水平拉伸时 banner 图未能居中,所以网上找了些资料,自己写了个小 demo html代码: <div class="div1& ...
- 如果非的让我引起大家的狂拍,那我说一句PHP是世界上最好的语言?
如果你进来了,那就达到了我的目的. 不知不觉.net已经用了3年之久,从最初的的小白到现在的大白,总有一种要骂娘的冲动,.net这一路走来现在越走越迷茫,不知道微软的重心在哪里,一直发现不了他的亮点所 ...
- react native 升级到0.31.0的相关问题 mac Android Studio开发环境
报错Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to com.facebook.re ...
- HTML基础知识入门
好的,我们开始吧,打开Eclipse,新建一个项目,就叫做Base吧,基础班的意思.注意哦,要建一个JavaWeb项目.右键,new,Dynamic Web Project,如果出来的菜单项没有,就点 ...