为什么计算机处理文本的能力这么重要?因为人类知识就是用文本记录流传的啊!

有人给Python起了个外号:“双管猎枪”。啥意思?Python有2/3版本之分,2和3的代码不能兼容。之所以会弄成这样,一个重要的原因就是:Python 2在设计开发的时候,没有考虑字符串的问题,内部实现不是UNICODE兼容的。当然,谁想得到这门语言日后会风行世界呢?这导致了Python 2处理字符串/文本,故障迭出,问题实在太多了。Python中文乱码问题,绝大部分都是Python 2版本导致的。

再加上其它一些因素,一狠心,仁慈的独裁者Guido – Python创造者,决定彻底重写Python,就是Python 3了。不要小看文本处理,这是人类文明的载体,一门语言对它的处理是否足够强大,直接决定了语言的竞争力。

这里面重要的概念是编码/解码。很多人会搞糊涂,.decode()和.encode()到底输出的是什么?作者总结了两句话:

把字节序列变成人类可读的文本字符串就是解码;把字符串变成存储或传输的字节序列就是编码

这里要注意:Python3的str基本相当于Python2的Unicode,造成不兼容的主要地方就在这里,不过也有一些补救措施。

编码/解码常见的异常错误是:UnicodeEncodeError和UnicodeDecodeError,引发异常的原因是什么?实际是代码使用的编解码器,无法处理输入的字符,它的字符序列里面没有那些,只能处理Unicode字符的一小部分子集,只好报错了。对于这种问题,基本上utf-8万能,按它操作。

对于计算机来说,实际它并不知道内存中存储的数据是什么 – 都是字节。而具体如何理解,那是人类自己定义的规则。如果告诉计算机,那是操作指令也行,只不过执行就会报错而已。C语言里面的指针,常有Cast操作,就是把要操作的数据,强制看成另外一种类型进行处理。这当然很强大,也很危险。

顺便说一句,JavaScript的坑比Python2/3更大,它诞生的时候,Unicode标准没有成型,所以采用了UCS-2编码。这导致了很多问题,后来不少引擎使用了UTF16实现。

处理文本的最佳实践是“Unicode三明治”:尽早的把输入字节序列解码成字符串,在其它处理过程不能编码/解码。在输出时,尽量晚的把字符串编码成字节序列。这是多数Web框架的操作准则,比如Django。

不同的Python版本在不同的平台,使用的默认编解码并非一致。所以为了操作一致性和避免问题,建议读写时候指定编解码,别依赖默认值,不然很容易填坑。

另外,Unicode文本处理带来了字符串比较/排序等一系列问题,需要使用对应的类库小心应对。

这章内容,可以结合其它资料一起看。

可用资源:Pragmatic Unicode—or—How Do I Stop the Pain?

再谈儒家文化理念和治国理想
流畅的Python-Fluent Python读书笔记-03-字典和集合