0. 环境


 

以下适用于Python3.6及以上

$ python
Python 3.6.3 (default, Oct 24 2017, 14:48:20) 
[GCC 7.2.0] on linux

 

1. 编码


 

关于ASCII、GBK、Unicode等字符集和编码的发展可以参考Python 编码为什么那么蛋疼? - 刘志军的回答 - 知乎,觉得说得挺好的,不过要小心的是回答中的有关代码是Python2的。

而关于字符集和编码的关系,参考字符集与编码,写得挺详细的。还能看看刨根究底学编程

简单来说,

在Python3中,默认的编码格式是utf-8:

>>> import sys
>>> sys.getdefaultencoding()
'utf-8'

那么可以说,在Python3中文本的编码格式(默认)都是utf-8(utf-8是Unicode的一种实现方式)。


 

2. str和bytes


 

首先,从Eli Bendersky's website借一副图:

在Python3中,但凡是文本,就一定是str类型,同时,strbytes都是。刚学习的时候会弄不清什么是编码什么是类型这里用代码解释一下。

>>> a_str = '中国'
>>> type(a_str)
<class 'str'>
>>> a_str_encode = a_str.encode()
>>> a_str_encode
b'\xe4\xb8\xad\xe5\x9b\xbd'

a_str这个变量,它是str类,也可以说它是str类型的数据,将它按照默认的编码格式去编码后得到a_str_encodea_str_encode的值是b'\xe4\xb8\xad\xe5\x9b\xbd',开头的b意味着后面跟着的这一串东西是bytes类型的数据,\x代表它和紧接着它的两个数字或者字母共同组成一个16进制数。b'\xe4\xb8\xad\xe5\x9b\xbd'有6个十六进制数,每三个表示一个汉字。而‘\xe4\xb8\xad’就是汉字“中”字的utf-8这种编码的16进制表示。


 

3. 各种转换


 

3.1 编码之间的转换

在第二节中,str类型有一个方法是encode,其等同于使用bytes函数显式转换:

>>> a_str_encode
b'\xe4\xb8\xad\xe5\x9b\xbd'
>>> b_str_bytes = bytes(a_str,'utf-8')
>>> b_str_bytes 
b'\xe4\xb8\xad\xe5\x9b\xbd'

要说一下ord这个函数,会输出Unicode编码的10进制:

>>> ord('中')
20013

那么如果要把一个utf-8编码的bytes转换成Unicode编码,也就是把中国人能看得懂的汉字转成utf-8之后,想把汉字转成unicode,那么只要先解码(变回去中国人能看懂的)再编码(变成计算机能看懂的):

>>> a_str.encode('utf-8').decode('utf-8').encode('unicode-escape')
b'\\u4e2d\\u56fd'

我在这里的理解是,把编码和解码都当作一种数据库的查询,而Unicode就是这个库,需要编码的时候就是在库里找到这个字对应的十六进制、十进制等等,解码就是相反的操作,但都是遍历字符串中的字符逐个去查询。

至于要将b'\\u4e2d\\u56fd'换成'\\u4e2d\\u56fd'只需要

>>> str(b'\\u4e2d\\u56fd',encoding='utf-8')
'\\u4e2d\\u56fd'

 

3.2 大端小端以及10进制整数转16进制

我的计算机默认的存储方式是小端:

>>> import sys
>>> sys.byteorder
'little'

对于一个整数10021,将其转成16进制、大端存储的方法有两种(之所以写两种方法是因为后一种可以补位数):

>>> hex(10021)
'0x2725'
>>> e_bytes = (10021).to_bytes(5,byteorder='big')
>>> e_bytes
b"\x00\x00\x00'%"

其中,输出的这串bytes里有'%'和''',其实,用ord函数算出它们的ASCII码并换成16进制:

>>> hex(ord('\''))
'0x27'
>>> hex(ord('%'))
'0x25'

那么最后的结果其实相当于b"\x00\x00\x00\x27\x25"。

>>> import binascii
>>> binascii.hexlify(e_bytes)
b'0000002725'

想直接得到一个10进制数转换成16进制数且是小端存储的方法:

>>> import binascii
>>> binascii.hexlify(b'10021')
b'3130303231'