str与字节码
首先,我们完全不谈unicode。
s = "人生苦短"
s是个字符串,它本身存储的就是字节码。那么这个字节码是什么格式的?
如果这段代码是在解释器上输入的,那么这个s的格式就是解释器的编码格式,对于windows的cmd而言,就是gbk。
如果将段代码是保存后才执行的,比如存储为utf-8,那么在解释器载入这段程序的时候,就会将s初始化为utf-8编码。
unicode与str
我们知道unicode是一种编码标准,具体的实现标准可能是utf-8,utf-16,gbk ……
python 在内部使用两个字节来存储一个unicode,使用unicode对象而不是str的好处,就是unicode方便于跨平台。
你可以用如下两种方式定义一个unicode:
s1 = u"人生苦短"
s2 = unicode("人生苦短", "utf-8")
encode与decode
# -*- coding:utf-8 -*-
su = "人生苦短"
# : su是一个utf-8格式的字节串
u = s.decode("utf-8")
# : s被解码为unicode对象,赋给u
sg = u.encode("gbk")
# : u被编码为gbk格式的字节串,赋给sg
print sg
# 打印sg这里写代码片
但是事实情况要比这个复杂,比如看如下代码:
s = "人生苦短"
s.encode('gbk') # 这的确是合理的 !!只是会报错而已
所以你看看!str也能编码,(事实上unicode对象也能解码,但是意义不大)
这样为什么可以?看上图的编码流程的箭头,你就能想到原理,当对str进行编码时,会先用默认编码将自己解码为unicode,然后在将unicode编码为你指定编码。
这就引出了python2.x中在处理中文时,大多数出现错误的原因所在:python的默认编码,defaultencoding是ascii
看这个例子:
# -*- coding: utf-8 -*-
s = "人生苦短"
s.encode('gbk') # 上面说过会报错的
UnicodeDecodeError: ‘ascii’ codec can’t decode byte ……
因为你没有指定defaultencoding,所以它其实在做这样的事情:
# -*- coding: utf-8 -*-
s = "人生苦短"
s.decode('ascii').encode('gbk') # 因为s是str,所以在decode('ascii')
# 的时候出错了,但是你decode('utf-8')就没事
设置defaultencoding
设置defaultencoding的代码如下:
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
如果你在python中进行编码和解码的时候,不指定编码方式,那么python就会使用defaultencoding(ascii)。
比如上一节例子中将str编码为另一种格式,就会使用defaultencoding。
s.encode("utf-8") # 等价于下一行
s.decode(defaultencoding).encode("utf-8")
# 就是前面的: s.decode('ascii').encode('utf-8')
再比如你使用str创建unicode对象时,如果不说明这个str的编码格式,那么程序也会使用defaultencoding。
u = unicode("人生苦短") 等价于 u = unicode("人生苦短",defaultencoding)
默认的defaultcoding:ascii是许多错误的原因!!!所以早早的设置defaultencoding是一个好习惯。
print()
关于print():
你在打印str的时候,实际就是直接将字节流发送给shell。如果你的字节流编码格式与shell的编码格式不相同,就会乱码。
而你在打印unicode的时候,系统自动将其编码为shell的编码格式,是不会出现乱码的。