@
KyL 你概念理解有错
首先,Python 2 unicode 和 str 转换方法要弄清楚:
str.decode('utf-8') -> unicode
unicode.encode('utf-8') -> str
我上例中 text.encode('utf-8') 后已经是 str 了。
然后你理解错了,str 并不是只能存储 ascii 类型的字符。str 存储的是一个一个的字节数据,也可以说就是一个一个字节的数字。然后这些数字代表的是什么字符,要看你用什么编码去解读它。
例如现在一个 str 用一个字节存储了数字 97,那么你用 ascii 编码去解读它,那么这个 str 就是 'a'。
然后现在有一个 str 用三个字节存储了三个数字:235、184 和 173,连起来用 16 进制表示也就是 '\xe4\xb8\xad'。然后你也可以用 ascii 编码去解读它,查 ascii 表后可以发现这三个数字都不在基本的 128 位 ascii 里,而是在扩展表里,都是一些很奇怪的字符,可见这个 str 用 ascii 编码去解读它对我们来说没有意义。
但是我们换一个编码 'utf-8' 去解读它,这个 str 就变得有意义了,在 utf-8 编码里是用三个字节来存储一个汉字字符的,而不是像 ascii 编码一个字节就对应了一个字符。那么 235、184 和 173 这三个字节的数字在 utf-8 编码里对应的就是一个汉字字符的 “中”。你可以用以下方法验证:
>>> char = u'中'
>>> print type(char)
<type 'unicode'>
>>> char = char.encode('utf-8')
>>> print type(char)
<type 'str'>
>>> print repr(char) # repr 方法可以将对象在 Python 内部的存储形式表现出来
'\xe4\xb8\xad'
>>> print char
中
>>> print '\xe4\xb8\xad'
中
在 print 这个 str 类型的 char 时,Python 只是把那三个数字直接发送给了用来显示的控制台(console)。console 就是用来输出的地方,例如 Sublime Text 的运行结果窗口,还有 Windows 下的 cmd。
然后决定用什么编码去解读它,是由 console 来决定的。在 Sublime Text 下这个编码默认是 utf-8,它用 utf-8 去解读 235、184 和 173 这三个数字,发现是 “中” 字,那么它就会去字库里找出 “中” 字这个字形给我们显示出来,因此我们就能看到 “中” 了。
而在 cmd 下,它用来解读的编码就不是 utf-8 了,而是 gbk 之类的。那它用 gbk 编码去解读这三个数字,可能它能找到另一些对应的字符,也有可能它完全找不到对应的字符,这时就产生了显示出乱码的情况。如果你想让它显示出 “中”,那么你就要让 Python 发送给它 gbk 编码下 “中” 所对应的数字,也就是 214 和 208,写成 16进制就是 '\xd6\xd0'。
因此你在 print 的时候想要显示正常,要看你现在的输出 console 用的是什么编码,然后就要发送给它对应编码的 str。
我最开始所说 html 是 utf-8 编码的 str,意思就是 html 里存储的字节序列,就是你想要的网页源码文字在 utf-8 编码下对应的一个个的数字,所以我们可以说它是 utf-8 编码的 str,因为它在 ascii 和 gbk 等编码下是没有意义的。Python 将它送给 Sublime Text, Sublime Text 也用 utf-8 编码去解读它,最后就能显示出你能看得懂的网页源代码文字。