Unicode 和UTF-8的关系
Unicode 是「字符集」
字符集:为每一个「字符」分配一个唯一的 ID(学名为码位 / 码点 / Code Point)
UTF-8 是「编码规则」
编码规则:将「码位」转换为字节序列的规则(编码/解码 可以理解为 加密/解密 的过程)
在Python2中,有两种字符串类型:str和unicode类型。
str存bytes数据/十六进制字节数据,unicode类型存unicode数据
# coding: UTF-8
u = '张a'
print type(u) # <type 'str'>
print repr(u) # '\xe5\xbc\xa0'
print type(u.decode('utf-8')) # <type 'unicode'>
print repr(u.decode('utf-8')) # u'\u5f20'
u = u'张a'
print type(u) # <type 'unicode'>
print repr(u) # u'\u5f20'
print type(u.encode('utf-8')) # <type 'str'> utf-8
print repr(u.encode('utf-8')) # '\xe5\xbc\xa0'
print type(u.encode('gbk')) # <type 'str'> gbk
print repr(u.encode('gbk')) # '\xd5\xc5'
为什么英文拼接成功了,而中文拼接就报错了?
这是因为在python2.x中,python解释器悄悄掩盖掉了 byte 到 unicode 的转换,只要数据全部是 ASCII 的话,所有的转换都是正确的,一旦一个非 ASCII 字符偷偷进入你的程序,那么默认的解码将会失效,从而造成 UnicodeDecodeError 的错误。python2.x编码让程序在处理 ASCII 的时候更加简单。你付出的代价就是在处理非 ASCII 的时候将会失败。
无论是utf-8还是gbk都只是一种编码规则,一种把unicode数据编码成字节数据的规则,所以utf-8编码的字节一定要用utf-8的规则解码,否则就会出现乱码或者报错的情况。
小结:
1.str就是经过编码的字符串
2.unicode是字符集可以转成utf-8,gbk等等
3.编码 unicode---其他编码 ,解码 其他编码-----unicode
在Python3.x中,也只有两种字符串类型:str和bytes类型。
str类型存unicode数据,bytse类型存bytes数据,与python2.x比只是换了一下名字而已。
u = '张a'
print (type(u)) # <type 'str'>
print (repr(u)) # '张a'
print (type(u.encode('utf-8'))) # <class 'bytes'> utf-8
print (repr(u.encode('utf-8'))) # b'\xe5\xbc\xa0a'
print (type(u.encode('gbk'))) # <class 'bytes'> gbk
print (repr(u.encode('gbk'))) # '\xd5\xc5'
当我们在编辑文本的时候,字符在内存对应的是unicode编码的,这是因为unicode覆盖范围最广,几乎所有字符都可以显示。但是,当我们将文本等保存在磁盘时,数据是怎么变化的?
答案是通过某种编码方式编码的bytes字节串。比如utf-8,一种可变长编码,很好的节省了空间;当然还有历史产物的gbk编码等等。于是,在我们的文本编辑器软件都有默认的保存文件的编码方式,比如utf-8,比如gbk。当我们点击保存的时候,这些编辑软件已经"默默地"帮我们做了编码工作。
那当我们再打开这个文件时,软件又默默地给我们做了解码的工作,将数据再解码成unicode,然后就可以呈现明文给用户了!所以,unicode是离用户更近的数据,bytes是离计算机更近的数据。
其实,python解释器也类似于一个文本编辑器,它也有自己默认的编码方式。python2.x默认ASCII码,python3.x默认的utf-8,可以通过如下方式查询:
import sys
print(sys.getdefaultencoding())
如果我们不想使用默认的解释器编码,就得需要用户在文件开头声明了。还记得我们经常在python2.x中的声明吗?
# encoding=utf8
如果python2解释器去执行一个utf-8编码的文件,就会以默认的ASCII去解码utf-8,一旦程序中有中文,自然就解码错误了,所以我们在文件开头位置声明 #coding:utf-8,其实就是告诉解释器,你不要以默认的编码方式去解码这个文件,而是以utf-8来解码。而python3的解释器因为默认utf-8编码,所以就方便很多了。
参考资料:
1. http://www.cnblogs.com/yuanchenqi/articles/5956943.html