坑爹的字符编码问题

昨晚看了一篇讲解 Python 中字节与字符串的文章,由此为开头,又开启了对 Python 中字符编码问题的探究。

以前粗略了解 ascii gbk utf-8 Unicode,大概掌握了 decode 和 encode 的概念,但越来越发现,仅仅这些概念还不够,还有一些东西需要了解清楚,否则只是盲目的 decode 来 encode 去的,很容易自己被自己搞晕。

首先要明确一点,2.x 和 3.x 中对字符串的表示有了根本的区别。

2.x 中,str 为某一种编码方式 encode 之后的字节码构成的字节流。

3.x 中,str 为 Unicode 对象,内部就是用的 Unicode 字符集里的字符,是真正意义上的字符串。

所以导致了一个很奇葩的事情的:

2.x 中 str 要选择合适的编码 decode 为 Unicode 字符集后才能转化为其它编码下的字节流,在 2.x 中就是 str。

3.x 中呢,多了一个类型,字节 byte

而 str 默认为 Unicode 对象,当然地,只有 encode 方法,不再有 decode 方法,啊,老天爷,绕死我了.

简而言之,在我们人类看起来没什么不同的字符串,在 2 和 3 中的 Python 眼中,已经成了完全不同的东西.而作为程序广义输入的的入口,这相当于我们输入给 Python 程序的东西,变了,这很蛋疼啊!

不过, 3.x 中的方法才是未来,尽量向这个方向靠是没错的。

所以,目前有一个比较好的处理方式。虽然 2.x 中没有字节的概念,但已经有了方法可以将 str 默认转化为 Unicode 对象.

from __future__ import unicode_literals

要注意的是,最好将 2.x 中默认的 str 编码方式设定为 utf-8,否则没法很好地支持国际化。其实汉语就是很国际化的代码了,就字符编码而言,挺复杂的。采用 utf-8 编码的好处是,你输入的字符串几乎都能得到支持,因为其背后用的字符集就是 Unicode 的字符集嘛。

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

容我再回味一下,在 2.x 中, unicode 对象可以 encode,但 str 默认是字节码,所以最好 decode 为 unicode 后再 encode 转码。如果将 str 直接 encode 也能运行,因为 Python 会自动先将 str 解码为 unicode 之后再编码,而坑爹的是:这里的解码用的是默认的 ascii。

在 3.x 中,才算正常,str 就是 Unicode 字符集,然后输出到控制台时,由控制台自行编码,输出到文件时,也可以由文件编辑器自行编码。

此外还有一点要注意,在 2.x 中,如果调用方法将 str 转化为 Unicode 对象,在输出控制时不会有问题,但在__write(‘filename’)__时仍会出问题,因为 write 方法不会自行编码,我们必须指定编码方式将 Unicode 编码为 str 类型。

所以,暂时就是又了解了这么些,字符集,字节流,Unicode,以及 2 和 3 的重大区别,以及怎么在 2 中采用默认 unicode 的字符串.

以后尽量这么对待字符串:就是将 str 都统一为 Unicode,让各个控制台去自己做决定,转化为人类可识别的字符.

还有一个方法:repr(string), 可以查看程序中 str 真正意义上是用什么格式存储的。在不确定的情况下,可以尝试用它来进行判断。


不知是该恭喜,还是该怎样,总之阅读到该文的,你是第 人。每一次刷新,都是不同的自己。