给小白写的 “搞懂 Python 中的编码”

栏目: Python · 发布时间: 7年前

内容简介:1. 原理:

很多初学者会被 Python 中UnicodeDecodeError弄得一头污水,相信你也一定遇到过这个问题,这里我们讲一下编码相关的知识。 (部分内容参考了 《编写高质量Python代码的59个有效方法》一书

1. 原理:

    计算机中所有的内容都是用1和0组成的(二进制)。 这和计算机的硬件实现原理相关,通常组成计算机的逻辑电路只有接通和断开两个状态,分别用来表示1和0。这样一个逻辑电路组成的位置叫一个比特(bit),一个位置能表示的内容有限,但组合起来,多个一起用就能发挥出无限威力,我们把8位放到一起组成一个 字节(Byte) 。可以得知,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),字节对应的二进制数字被用来表示大小写英文字母、数字和一些符号,比如65代表大写字母A,122代表小写字母z,这个对应关系就是 ASCII编码表, ASCII是American Standard Code for Information Interchange的简称,是为美国英语而设计的。

ASCII 码使用指定的 7 位 或 8 位二进制数组合来表示 128 或 256 种字符。 标准ASCII 码也叫基础ASCII码,使用 7 位二进制数(最开始的那1位固定为0) 简称 7位ASCII 来表示所有的大写和小写字母,数字0 到9、标点符号, 以及在美式英语中使用的特殊控制字符。

有了这个编码表,在计算机中处理大小英文,数字,标点基本上够用了,但问题是我们的中文有非常多汉字,总数超过了8万,常用的都有3500个之多,更何况世界上还有各种其它语言,那么在计算机中怎么表示数量这么庞大的字符呢?

解决这个问题很简单,每个字符用多个字节来表示,一个不够用两个,两个不够用三个,使用足够多的字节肯定是能表示出来的。使用这种“原始”的多个字节值表示其它的复杂字符,这些8位称为 原始8位值。

但问题又来了,各平台,各国家规定都不统一,同样的编码,在一个国家表示某个文字,在另一个国家可能被用来表示另一个文字,在信息交流的时候经常会出现“乱码”。为了解决这个问题,必须得有统一的标准,于是Unicode(统一码、万国码、单一码)就诞生了。Unicode 也称为 UCS(Universal Coded Character Set: 国际编码字符集合) 是一个字符集合。UNICODE标准也在不断发展完善,目前使用 4个字节 表示一个字符可以表示出全世界所有字符。那UNICODE在计算机中如何存储呢,存储时也必须占用4个字节么,这就要涉及到编码的知识。

    UNICODE最常见的编码方式是UTF-8 ,另外还有UTF-16,UTF-32等。如果每个字符都用四个字节来存储,纯英文内容占用空间变成了原来ASCII的四倍,非常浪费空间。而UTF-8编码比较巧妙,采用的是变长的方法,也就是一个字符在UTF-8编码表示时占用1个字节到4个字节不等,兼容ASCII,表示纯英文时,并不会占用更多长度。

2. 转换过程

UTF-8,GBK等,通过 解码(decode) 得到UNICODE,UNICODE通过 编码(encode) 可以转换成GBK或UTF8等编码( 原始8位值 ),转换如下图所示。

给小白写的 “搞懂 Python 中的编码”

3. 示例:

u'6啊'.encode('utf8')  ->  b'6\xe5\x95\x8a'(16进制表示的 原始8位值

u'6啊'.encode('gbk')  ->  b'6\xb0\xa1'       (16进制表示的 原始8位值

从上面的例子可以看到6是用一个字节表示的,汉字“啊”在utf8中是用三个字节表示的(gbk中是两个字节),其中\xe5意思就是16进制的e5,代表一个8位二进制:

bin(int('e5', base=16)) -> '0b11100101'。

再比如 “涂 这个汉字,unicode 为 u'\u6d82'

使用utf8编码时 '\xe6\xb6\x82'  11100110  10110110  10000010  三个8位

使用gbk编码时 '\xcd\xbf'          11001101  10111111  两个8位

4. 结论:

4.1 Unicode可以通过不同的字符编码来实现,最常用的是utf8,它是ASCII码的超集。

4.2 Python 3 有两种表示字符序列的类型:bytes 和 str。bytes 的实例包含原始的8位值,str 的实例包含unicode字符。

4.3 Python 2 也有两种表示字符序列的类型 ,分别叫做 str 和 unicode。与Python3不同的是,Python2中 str 实例包含原始的8位值;而unicode的实例,则包含unicode字符。Python2里面 不够严格 ,如果str只包含7位ASCII字符,那么unicode和str实例似乎就成了同一种类型: a) 可以相加 b) 可以比较 c) 可以用 %s 格式化。如果使用的时候不注意在特定的场景下就会带来问题。

4.4 在编程时,编码和解码尽量在最外围做 ,程序处理逻辑中尽量全部使用unicode,当有必要时( 比如写入到文件 )才 encode 转换成utf8等编码

从文件等中读取后尽快decode转换成unicode。这样可以大大减少编码带来的问题。

5. 读者思考:

1. utf8为什么这么成功,它是如何兼容ASCII的?

2. 通过上面的示例,是不是发现用gbk存储中文比utf8更省空间,那为什么一般情况下不用gbk来储存,而是用utf8呢?

给小白写的 “搞懂 Python 中的编码”


以上所述就是小编给大家介绍的《给小白写的 “搞懂 Python 中的编码”》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Code Reading

Code Reading

Diomidis Spinellis / Addison-Wesley Professional / 2003-06-06 / USD 64.99

This book is a unique and essential reference that focuses upon the reading and comprehension of existing software code. While code reading is an important task faced by the vast majority of students,......一起来看看 《Code Reading》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换