在实践中,很多初学者都遇到过“文件显示乱码”的情况,其多数都是由于在打开文件时,没有选对编码格式导致的。因此,学习 Python 中的字符或字符串,了解其底层的编码格式是非常有必要的。
鉴于有些读者并不了解什么是编码格式,本节先从编码开始讲起。
虽然很多教程中有关于编码的定义,但对初学者来说并不容易理解,这里先举一个例子。古代打仗,击鼓为号、鸣金收兵,即把要传达给士兵的命令对应为公认的其他形式,这就和编码有相似之处。
以发布进攻命令为例,相比用嗓子喊,敲鼓发出的声音传播的更远,并且士兵听到后也不会引起歧义,因此长官下达进攻命令后,传令员就将此命令转化为对应的鼓声,这个转化的过程称为编码;由于士兵都接受过训练,听到鼓声后,他们可以将其转化为对应的进攻命令,这个转化的过程称为解码。
需要说明的是,此例只是形象地描述了编码和解码的原理,真实的编码和解码过程比这要复杂的多。
了解了编码的含义之后,接下来再介绍一下字符编码。
我们知道,计算机是以二进制的形式来存储数据的,即它只认识 0 和 1 两个数字。 20 世纪 60 年代,是计算机发展的早期,这时美国是计算机领域的老大,它制定了一套编码标准,解决了 128 个英文字符与二进制之间的对应关系,被称为 ASCII 字符编码(简称 ASCII 码)。
ASCII 码,全称为美国信息交换标准代码,是基于拉丁字母的一套字符编码,主要用于显示现代英语,因为万维网的出现,使得 ASCII 码广为使用,其直到 2007 年 12 月才逐渐被 Unicode 取代。
虽然英语用 128 个字符编码已经够用,但计算机不仅仅用于英语,如果想表示其他语言,128 个符号显然不够用,所以很多其他国家都在 ASCII 的基础上发明了很多别的编码,例如包含了汉语简体中文格式的 GB2312 编码格式(使用 2 个字节表示一个汉字)。
也正是由于出现了很多种编码格式,导致了“文件显示乱码”的情况。比如说,发送邮件时,如果发信人和收信人使用的编码格式不一样,则收信人很可能看到乱码的邮件。基于这个原因,Unicode 字符集应运而生。
Unicode 字符集又称万国码、国际码、统一码等。从名字就可以看出来,它是以统一符号为目标的字符集。Unicode 对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更简单的方式来呈现和处理文字。
注意,在实际使用时,人们常常混淆字符集和字符编码这两个概念,我认为它们是不同的:
Unicode 字符集可以使用的编码方案有三种,分别是:
其中,UTF-8 是目前使用最广的一种 Unicode字符集的实现方式,可以说它几乎已经一统江湖了。
了解了什么是编码,以及什么是字符编码之后,最后解决“Python 使用哪种字符编码?”这个问题。
Python 3.x 中,字符串采用的是 Unicode 字符集,可以用如下代码来查看当前环境的编码格式:
同时,在 Python 3.x 中也可以用 ord() 和 chr() 函数实现字符和编码数字之间的转换,例如:
Python 2.x 中无法使用 ord() 得到指定字符对应的编码数字。
由此可以知道,在 Unicode 字符集中,字符‘Q’对应的编码数字为 81,而中文‘网’对应的编码数字为 32593。
值得一提的是,虽然 Python 默认采用 UTF-8 编码,但它也提供了 encode() 方法,可以轻松实现将 Unicode 编码格式的字符串转化为其它编码格式。有关 encode() 方法的用法,可阅读《Python encode()和decode()方法》 一节。