当前位置:   article > 正文

py2: str和unicode_python union[str, unicode]

python union[str, unicode]

unicode和utf8

  • Unicode 是「字符集」字符集:为每一个「字符」分配一个唯一的 ID(学名为码位 / 码点 / Code Point)
  • UTF-8 是「编码规则」编码规则:将「码位」转换为字节序列的规则(编码/解码 可以理解为 加密/解密 的过程)

Unicode 字符集为每一个字符分配一个码位,例如「知」的码位是 30693,记作 U+77E5\u77e530693 的十六进制为 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
  • 1
  • 2
  • 3
  • 4

根据上表中的编码规则,之前的「知」字的码位 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这就是将 U+77E5 按照 UTF-8 编码为字节序列 E79FA5 的过程。

py2的str和unicode

py2的unicode就是字符对应的unicode码的字符串,例如上午的unicode码就是\u4e0a\u5348

s=u"上午"
u'\u4e0a\u5348'
  • 1
  • 2

所以说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'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

那就好理解了,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'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

我们用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)
  • 1
  • 2
  • 3

这是因为我们对unicode执行编码,环境的默认编码是ascii,通过下面代码将环境的默认编码转为utf8,发现执行就没有问题了

reload(sys)
sys.setdefaultencoding('utf-8')
str(u"知")
Out[15]: '\xe7\x9f\xa5'
  • 1
  • 2
  • 3
  • 4

还有一种操作是对str字节码执行encode,这里其实是执行的str.decode.encode,只要我们设置了默认的编码utf8后是不会报错的

"知".encode('gbk') # "知".decode('utf8').encode('gbk')
Out[16]: '\xd6\xaa'
  • 1
  • 2

最后一点,我们输入一个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
  • 1
  • 2
  • 3

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Unicode 和 UTF-8 有什么区别?
谈谈python2,3中的str、unicode

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/198980
推荐阅读
相关标签
  

闽ICP备14008679号