Python的字符编码

本篇内容涉及

  1. 二进制
  2. 二进制与ASCII码
  3. 字符编码的发展与介绍
  4. 十六进制

 

二进制


相信你们都知道进制的含义,咱们使用最普遍也最贴近实际生活的就是十进制,逢十进1、借一当十。在其余领域中被普遍使用的还有二进制、八进制和十六进制,每种进制都有其有点和擅长的领域。二进制是计算技术中普遍采用的一种数制。二进制数是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。计算机中的二进制则是一个很是微小的开关,用“开”来表示1,“关”来表示0,由于计算机内部的CPU包含上百万个精巧的晶体管的芯片集合的集成电路,一条路要么就经过,要么就关闭,用二进制的 0、1 最为合适了。这也是为何布尔值的True和False对应一、0了。固然一些运算也会涉及到八进制、十进制、十六进制,它们的转换关系如何呢?python

这里先给你们介绍三个内置方法(BIF built-in function),所谓内置方法,就是为了方便写代码,能够直接调用的方法,例如print、input等。这三个内置方法用来进行进制转换,括号内输入十进制整数,转换后获得字符串。编程

   二进制转换:bin() ---> ‘0b’(01)数组

   八进制转换:oct() ---> ‘0o’(01234567)网络

十六进制准换:hex() ---> ‘0x’(0123456789abcdef)ui

>>> a = 10
>>> bin(a),oct(a),hex(a) ('0b1010', '0o12', '0xa')

 

二进制与ASCII码


计算机只认识二进制,生活中的数字要想让计算机理解就必须转换成二进制。十进制到二进制的转换只能解决计算机理解数字的问题,那么文字要怎么让计算机理解呢?这时,ASCII码应运而生。将计算机须要识别的文字、符号、数字等等编辑在一张表里,每个字符都对应一个十制数,再把这个十进制数转换成二进制,计算机就认识了。编码

ascii

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其余西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO/IEC 646。最先只有127个字母被编码到计算机里,后来扩展了一些乱七八糟的的东西进去变成255个,正好被8位二进制数表示。因此就肯定无论是哪一个字符,都要以8位二进制数来表示,便于计算机识别,不然很容易乱。spa

好比我如今想表示 ‘hello’,应该以下:翻译

hello

在这里,每一位0或者1所占的空间单位为bit(比特),这是计算机中最小的表示单位,每8个bit组成一个字节byte,用B来表示。这是计算机中最小的存储单位(毕竟你是没有办法存储半个字符的)。设计

8bit = 1byte 字节,最小的存储单位,1byte缩写为1B  1KB=1024B
1MB=1024KB
1GB=1024MB
1TB=1024GB 等等。。。

 

字符编码的发展介绍


因为计算机在美国发明,固然没有考虑到别的国家也须要识别本国字符,尤为像中国,历史悠久,须要编码识别的字更是数不胜数。3d

GB2312

当计算机来到中国,根本就不认识中国的文字,壮哉我大中国自力更生,本身重写一张表,直接生猛地将扩展的第八位对应拉丁文所有删掉,规定一个小于127的字符的意义与原来相同,原本128-255之间的字符使用频率极低,连续使用两次机率更低,因此两个大于127的字符连在一块儿时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE,高低字节组合相似于横纵坐标,这样咱们就能够组合出大约7000多个简体汉字了;这种汉字方案叫作 “GB2312”。GB2312 启用于1980年,是对 ASCII 的中文扩展。 只收录简化字汉字,以及通常经常使用字母和符号,主要通行于中国大陆地区和新加坡等地,共收录有 7445 个字符,其中简化汉字 6763 个,字母和符号 682 个。

GBK

可是汉字太多了,GB2312根本不够用,因而规定:只要第一个字节是大于127就固定表示这是一个汉字的开始,无论后面跟的是否是扩展字符集里的内容。扩展以后的编码方案被称为 GBK 标准,GBK 包括了 GB2312 的全部内容,同时又增长了近20000个新的汉字(包括繁体字)和符号。GBK编码方案于1995年10月制定, 1995年12月正式发布,兼容GB2312,共有23940个码位,共收录了21003个汉字。

GB18030

GB18030有两个版本:GB18030-2000和GB18030-2005。GB18030-2000是GBK的取代版本,它的主要特色是在GBK基础上增长了CJK统一汉字扩充A的汉字。GB18030-2005的主要特色是在GB18030-2000基础上增长了CJK统一汉字扩充B的汉字。GB18030-2000仅规定了经常使用非汉字符号和27533个汉字(包括部首、部件等)的编码。GB18030-2005在GB18030-2000的基础上增长了42711个汉字和多种我国少数民族文字的编码。

Unicode

在中国字符编码蓬勃发展的时候,其余国家也在扩展本身的字符编码,如日本的Shift-JIS、韩国的ks_c_5601-1987等等,彼此之间倒是互不支持的。这就致使每一个国家都有本身的编码,拿着我国的编码到日本就变成乱码。因而,国际标谁化组织为了统一编码:提出了标准编码准则:Unicode 。Unicode是能够容纳世界上全部文字和符号的字符编码方案。目前的Unicode字符分为17组编排,0x0000 至 0x10FFFF,每组称为平面(Plane),而每平面拥有65536个码位,共1114112个。然而目前只用了少数平面。Unicode在1990年开始研发,1994年正式公布。Unicode编码,每个字符都是由16位二进制数组成的,大小为两个字节。因为Python的诞生比Unicode标准发布的时间还要早,因此最先的Python2.x版本默认编码为ASCII码。

utf-8

Unicode字符编码兼容ASCII码,可是却比原ASCII码里的字符比原来大了一倍。这下英文世界的人们不干了,由此产生了新的编码规则,UTF-8。UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,当字符在ASCII码的范围时,就用一个字节表示。可是对其他地区不太友好,欧洲语系须要2个字节、东亚地区须要3个字节,其它及特殊字符会须要4个字节等等。不过写代码嘛,用到的中文不多,因此也就不在意了。虽然在咱们内存中的数据都是unicode,但当数据要保存到磁盘或者用于网络传输时,直接使用unicode就远不如utf-8省空间啦! 这也是为何utf-8是咱们的推荐编码方式。 总结来讲:UTF 是为unicode编码 设计 的一种 在存储 和传输时节省空间的编码方案。


 

十六进制


先给你们看一个例子,还记得字符串的encode()方法吧:

QQ截图20190213215210

不是说计算机都是用二进制的么?为何转换成bytes类型后显示的倒是十六进制呢?这是由于十六进制更简短,一位十六进制数等于4位二进制数。比方说ASCII码,是由8bit表示一个字符,那么若是用十六进制只须要2位就能够了,虽然这个样子咱们仍是看不懂,可是这种表现形式仍是要优于0101的,最后为了统一规范,CPU、内存等都是采用十六进制。不仅是计算机,在网络编程的数据传输也是经过十六进制传输的。

二进制与十六进制相互转换

熟记这个对应表,转换过程会事半功倍。

16进制2进制对应关系

二进制到十六进制

二进制到十六进制,采用去四合一法,以小数点为分界,整数部分向左、小数部分向右,每四位二进制换成一位十六进制,小数点位置保持不变。若是到最高位(或最低)不足四位,直接在最高位(或最低)补0。转换完后,如何分辨这个数是那种进制呢?十六进制的表示法,须要加上前缀‘0x’或者后缀‘h’,像刚刚看到的计算机里表示方法是使用前缀,可是把0省略了。

QQ截图20190214095955

十六进制到二进制

十六进制到二进制,就是反过来,每一个十六进制位都用四个二进制替换,小数点依然位置不动。

QQ截图20190214101425


 

字符编码


说了这么多,字符编码和写程序有什么关系呢?这里关系但是太大了。首先,咱们在计算机内存储的数据或者是进行网络传输的数据,必定是要按照某一种编码格式,这样计算机才能根据该编码格式将数据转换成0101的格式进行操做,而要读取数据和接收数据时,也是必定要按照相同的编码格式来,不然就会出现乱码。

>>> s = "你好"
>>> s.encode('utf-8') b'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> s.encode('gbk') b'\xc4\xe3\xba\xc3'
>>> # 能够看出,utf-8和gbk编码的长度都是不同的

代码的编码(文件编码)

首先一个程序的代码也就是源代码文件是有编码格式的,因此你编写的代码也必定是按照事先规定好的编码格式存储、执行或传输的。在Python3.x版本后,当咱们在写一个代码脚本的时候,发现咱们根本就没有这么一个步骤去告诉Python解释器这些代码是什么格式的编码。那是由于Python有默认的字符编码,那就是<utf-8>,也就是说你不用刻意地告诉Python这些代码应该按什么编码格式存储,Python已经帮你设置好了。固然代码的编码能够根据你的需求更改。相信在看过一些代码或者脚本后,你会发现好多人代码的第一行都有这样一句:

# -*- coding:utf-8 –*-

没错,这句话就是声明接下来你要写的全部代码应该按照何种编码格式存储和执行。由于Python3.x版本后默认就是utf-8,而且多数程序也都是以utf-8格式写的,因此并不须要强加这句。固然,若是你要改的话,比方说改为gbk格式,那就必要在最最最最上面加上这句话,声明整篇都是gbk。

# -*- coding:gbk –*-

因此说Python代码执行的过程大体上是这样的:

1. 首先写好的 .py 文件会按照文件头声明的编码格式存储到硬盘上(encode编码),若是没有指定编码格式就按照默认的编码格式来。

2. 要运行文件时,解释器首先找到 .py 文件,将文件按照开头指定的编码格式将代码加载到内存中,并所有转换成unicode格式。

3. 而后就是开始对代码进行解释,最后执行。

补充:咱们能够经过Python自带模块来查看当前的解释器的默认编码。

# Python2
import sys sys.getdefaultencoding() # 输出'ascii'

# Python3
import sys sys.getdefaultencoding() # 输出'utf-8'

字符串的编码

再说字符串的编码以前,必定要区分好字符串和字节串。字符串就是咱们能直观看懂的,平常生活中使用的沟通交流的语言符号。而字节串是计算机能看懂的一堆二进制码。字符不等于字节,可是二者之间存在转换关系(字符编码)。根据选取的字符集的不一样转换结果不同,也就是咱们上面所说的各类字符编码。而在Python3.x中已经实现了unicode的内置支持,而Python3.x中字符的形式只有两种一种就是以unicode格式显示的字符串,一种就是bytes类型的字节串。以unicode格式显示的字符串是直接可读的,因此只有unicode是真正的字符串。

# unicode字符串
str1 = '你好'

# bytes类型字节串
str2 = b'abc'  # 字符串前加b就表示bytes类型,这种写法只支持ascii码
str3 = b'\xe4\xbd\xa0\xe5\xa5\xbd'  # '你好'转换的字节串

因为Python3.x定义的字符串默认就是unicode,而且unicode编码含有全部字符编码的映射关系,因此unicode格式的字符串没办法被decode(解码)操做,只能进行encode(编码)操做,转换成为utf-八、gbk、gb2312等编码格式的bytes类型字节串。而字节串能够经过decode(解码)操做转换回unicode格式。之间的转换关系以下图:

字符编码转换关系

各个字符编码在转换的时候必定不要混搭,不然就会出现下面的状况(乱码或者不是原来的样子):

>>> a = '你好'  # 此时必定是unicode编码
>>> b = a.encode('utf-8')  # b从unicode转换成utf-8
>>> b b'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> c = b.decode('gbk')  # c按照gbk编码转换成unicode
>>> c '浣犲ソ' 
# 转换回去已经不是'你好'了

一个字符串按照某种编码格式编码成字节串,这个字节串想要解码成字符串必定要遵守以前的编码格式,好比中文按照utf-8编码,每一个字符是三个字节,而按照gbk解码成字符串时每一个字符只有两个字节,这样在字符完成解码时,至少字符个数上就会发生变化,若是编码的互相对应不上的话就会出现乱码。

 

PS:任何一种编码都不会解决语言种类的问题。比方说用日本的编码格式Shift_JIS编写的软件拿到中国来,通常中国的Windows系统默认编码都是gbk格式,以gbk去显示Shift_JIS确定是对应不上的,因此该软件没法正常显示。可是电脑都支持unicode,若是把软件的编码转换为unicode,而Unicode又包含全部编码的映射,这样就能够正常显示了,可是必定注意,显示的是日文,而不是中文,正常显示的意思就是显示的是正确的字符,但可没有解决翻译语言的问题。

 

 总结

若是在Python3.x中出现字符编码的问题,那么无外乎就是下面几种状况:

1. Python解释器默认编码

2. py文件源代码的编码

3. 字符串和字节串的编码

4. 系统默认编码

以上这几处所使用的编码没有对应好。


 

python2.x简介

Python2的默认编码是ASCII码,这就致使python想要显示中文等必需要在文件头声明字符编码。

python2中,字符串有三个类型:str、bytes、unicode。str和bytes两类是能够直接划等号的,都属于字节串。而unicode才是真正的字符串。因此当你定义一个 str类型变量的时候,你觉得是字符串,其实就是bytes类型。

最后,为了知足pytohn2 和 python3 的兼容性,尽可能在文件头加上 # -*- coding:gbk –*-

相关文章
相关标签/搜索