赞
踩
Unicode 字符集为每一个字符分配一个码位,例如「知」的码位是 30693
,记作 U+77E5
或\u77e5
(30693
的十六进制为 0x77E5
)。
UTF8编码做的是将对应的码位编码到字节序列。
U+ 0000 ~ U+ 007F: 0XXXXXXX
U+ 0080 ~ U+ 07FF: 110XXXXX 10XXXXXX
U+ 0800 ~ U+ FFFF: 1110XXXX 10XXXXXX 10XXXXXX
U+10000 ~ U+1FFFF: 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX
根据上表中的编码规则,之前的「知」字的码位 U+77E5 属于第三行的范围:
7 7 E 5
0111 0111 1110 0101 二进制的 77E5
--------------------------
0111 011111 100101 二进制的 77E5
1110XXXX 10XXXXXX 10XXXXXX 模版(上表第三行)
11100111 10011111 10100101 代入模版
E 7 9 F A 5
这就是将 U+77E5 按照 UTF-8 编码为字节序列 E79FA5 的过程。
py2的unicode就是字符对应的unicode码的字符串,例如上午
的unicode码就是\u4e0a\u5348
s=u"上午"
u'\u4e0a\u5348'
所以说unicode是很好理解的就是没有经过编码的unicode码的字符串
str格式的本质含义则是“某种编码格式”,来看一下
s1="上午"
>> '\xe4\xb8\x8a\xe5\x8d\x88'
s1.decode('utf8')
>> u'\u4e0a\u5348'
s2="知"
>> '\xe7\x9f\xa5' # 可以看到是对应上面的例子
s2.decode('utf8')
>> u'\u77e5'
那就好理解了,unicode是没有经过编码的,而str是经过编码后的字节数组,两者转化就是编码解码的问题了。
我们把s1和s2解码可以看到就是unicode
s1="上午"
Out[7]: '\xe4\xb8\x8a\xe5\x8d\x88'
s1.decode('utf8')
Out[8]: u'\u4e0a\u5348'
s2="知"
Out[9]: '\xe7\x9f\xa5' # 可以看到是对应上面的例子
s2.decode('utf8')
Out[10]: u'\u77e5'
unicode再转为str,unicode 编码 encode
s1="上午"
s.decode('utf8').encode('utf8')
Out[11]: '\xe4\xb8\x8a\xe5\x8d\x88'
s2="知"
s2.decode('utf8').encode('utf8')
Out[12]: '\xe7\x9f\xa5'
我们用str对unicode执行编码是最容易出错的UnicodeEncodeError: 'ascii' codec can't encode character u'\u77e5' in position 0: ordinal not in range(128)
s2=u"知"
str(s2)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u77e5' in position 0: ordinal not in range(128)
这是因为我们对unicode执行编码,环境的默认编码是ascii,通过下面代码将环境的默认编码转为utf8,发现执行就没有问题了
reload(sys)
sys.setdefaultencoding('utf-8')
str(u"知")
Out[15]: '\xe7\x9f\xa5'
还有一种操作是对str字节码执行encode,这里其实是执行的str.decode.encode
,只要我们设置了默认的编码utf8
后是不会报错的
"知".encode('gbk') # "知".decode('utf8').encode('gbk')
Out[16]: '\xd6\xaa'
最后一点,我们输入一个str的编码格式与操作系统有关系,window通常是gbk,linux通常是utf8。
相信通过上面例子,再也不会怕看到UnicodeEncodeError: 'ascii' codec can't encode character
我们在没有设置py2默认编码时,比较一个str和unicode会出现如下提示:
>>>u'为' == '为'
False
UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
我们可以运行'为'.decode()
,会提示错误:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)
这其实就是上述warning的来源,当decode失败,默认认为str和unicode not equal
我们加上
>>>import sys
>>>reload(sys)
>>>sys.setdefaultencoding('utf8')
>>>u'为' == '为'
True
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。