游戏开发工具

在实践中,很多初学者都遇到过“文件显示乱码”的情况,其多数都是由于在打开文件时,没有选对编码格式导致的。因此,学习 Python 中的字符或字符串,了解其底层的编码格式是非常有必要的。

鉴于有些读者并不了解什么是编码格式,本节先从编码开始讲起。

什么是编码?

虽然很多教程中有关于编码的定义,但对初学者来说并不容易理解,这里先举一个例子。古代打仗,击鼓为号、鸣金收兵,即把要传达给士兵的命令对应为公认的其他形式,这就和编码有相似之处。

以发布进攻命令为例,相比用嗓子喊,敲鼓发出的声音传播的更远,并且士兵听到后也不会引起歧义,因此长官下达进攻命令后,传令员就将此命令转化为对应的鼓声,这个转化的过程称为编码;由于士兵都接受过训练,听到鼓声后,他们可以将其转化为对应的进攻命令,这个转化的过程称为解码。

需要说明的是,此例只是形象地描述了编码和解码的原理,真实的编码和解码过程比这要复杂的多。

了解了编码的含义之后,接下来再介绍一下字符编码。

什么是字符编码?

我们知道,计算机是以二进制的形式来存储数据的,即它只认识 0 和 1 两个数字。 20 世纪 60 年代,是计算机发展的早期,这时美国是计算机领域的老大,它制定了一套编码标准,解决了 128 个英文字符与二进制之间的对应关系,被称为 ASCII 字符编码(简称 ASCII 码)。

ASCII 码,全称为美国信息交换标准代码,是基于拉丁字母的一套字符编码,主要用于显示现代英语,因为万维网的出现,使得 ASCII 码广为使用,其直到 2007 年 12 月才逐渐被 Unicode 取代。

虽然英语用 128 个字符编码已经够用,但计算机不仅仅用于英语,如果想表示其他语言,128 个符号显然不够用,所以很多其他国家都在 ASCII 的基础上发明了很多别的编码,例如包含了汉语简体中文格式的 GB2312 编码格式(使用 2 个字节表示一个汉字)。

也正是由于出现了很多种编码格式,导致了“文件显示乱码”的情况。比如说,发送邮件时,如果发信人和收信人使用的编码格式不一样,则收信人很可能看到乱码的邮件。基于这个原因,Unicode 字符集应运而生。

Unicode 字符集又称万国码、国际码、统一码等。从名字就可以看出来,它是以统一符号为目标的字符集。Unicode 对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更简单的方式来呈现和处理文字。

注意,在实际使用时,人们常常混淆字符集和字符编码这两个概念,我认为它们是不同的:

1、字符集定义了字符和二进制的对应关系,为每个字符分配了唯一的编号。可以将字符集理解成一个很大的表格,它列出了所有字符和二进制的对应关系,计算机显示文字或者存储文字,就是一个查表的过程;

2、而字符编码规定了如何将字符的编号存储到计算机中,要知道,有些字符编码(如 GB2312 和 GBK)规定,不同字符在存储时所占用的字节数是不一样的,因此为了区分一个字符到底使用了几个字节,就不能将字符的编号直接存储到计算机中,字符编号在存储之前必须要经过转换,在读取时还要再逆向转换一次,这套转换方案就叫做字符编码。


Unicode 字符集可以使用的编码方案有三种,分别是:

1、UTF-8:一种变长的编码方案,使用 1~6 个字节来存储;

2、UTF-32:一种固定长度的编码方案,不管字符编号大小,始终使用 4 个字节来存储;

3、UTF-16:介于 UTF-8 和 UTF-32 之间,使用 2 个或者 4 个字节来存储,长度既固定又可变。


其中,UTF-8 是目前使用最广的一种 Unicode字符集的实现方式,可以说它几乎已经一统江湖了。

Python使用哪种字符编码?

了解了什么是编码,以及什么是字符编码之后,最后解决“Python 使用哪种字符编码?”这个问题。

Python 3.x 中,字符串采用的是 Unicode 字符集,可以用如下代码来查看当前环境的编码格式:

>>> import sys
>>> sys.getdefaultencoding()
'utf-8'

同时,在 Python 3.x 中也可以用 ord() 和 chr() 函数实现字符和编码数字之间的转换,例如:

>>> ord('Q')
81
>>> chr(81)
'Q'
>>> ord("网")
32593
>>> chr(32593)
'网'

Python 2.x 中无法使用 ord() 得到指定字符对应的编码数字。

由此可以知道,在 Unicode 字符集中,字符‘Q’对应的编码数字为 81,而中文‘网’对应的编码数字为 32593。

值得一提的是,虽然 Python 默认采用 UTF-8 编码,但它也提供了 encode() 方法,可以轻松实现将 Unicode 编码格式的字符串转化为其它编码格式。有关 encode() 方法的用法,可阅读《Python encode()和decode()方法》 一节。