Python2 解释器在加载 .py 文件中的代码时,会对内容进行编码(默认 ASCILL),而 Python3 对内容进行编码的默认为 UTF-8 而字符串则是 Unicode PyChram 自行把字符串转换成了 utf-8。
ASCII(American Standard Code for Information Interchange,美国标准信息交换代码)是基于拉丁字母的一套电脑编码系统,由 0 1 组成主要用于显示现代英语和其他西欧语言,其最多只能用 8 位来表示(一个字节),即:2**8 = 256 (因为计算编码是由 0 1 组成的个数是 2 而 ASCII 最多是8位,所以 2^8 = 256),所以,ASCII码最多只能表示 256 个符号。
ASCII码 面试题:ASCII码 第一位都是什么 0 (因为 ASCII码 起初设置的时候是 7位 后来觉得不够才添加了 1 位,所以所有 ASCII码的第一位都是 0)
然而中国的汉字就有 9万 多个,显然 ASCII 码无法将世界上的各种文字和符号全部表示,所以,就需要新出一种可以代表所有字符和符号的编码,即:Unicode
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码
Unicode 起初给了中文 2个字节(16位 )最多能表示 2 ** 16 = 65536 中文
后来觉得不够就给了 4个字节(32位) 最多表示 2 ** 32 = 4294967296 中文
然而,Unicode中的英文还是中文都是使用32位表示的, 后来觉得 32位 来表达一个汉字太浪费了随后就推出了 升级版 UTF-8 1个字节(8位)表示英文,3个字节(24位)表示中文
window系统的编码是 GBK
ASCII
英文 -> A : 00000010 8位 1个字节 表示1个字符
Unicode
之前
英文 -> A : 00000000 00000001 16位 2个字节表示1个字符
中文 -> 杨 : 00000000 00000001 16位 2个字节 表示1个字符
之后
英文 -> A : 00000000 00000001 00000010 00000100 32位 4个字节表示1个字符
中文 -> 杨 : 00000000 00000001 00000010 00000110 32位 4个字节 表示1个字符
UTF-8
英文 -> A : 00000010 8位 1个字节 表示1个字符
欧洲 -> 00000000 00000011 16位 2个字节 表示1个字符
中文 -> 杨 : 00000000 00000001 00000010 24位 3个字节 表示1个字符
GBK
英文 -> A : 00000010 8位 1个字节 表示1个字符
中文 -> 杨 : 00000000 00000001 16位 2个字节 表示1个字符
1. 各个编码之间的二进制,是不能互相识别的,会产生乱码。
2. 文件的储存,传输,不能是Unicode(只能是utf-8 utf-16 gbk,gb2312,asciid等,因为 Unicode 占用内存太大)
3. 在 Python3 中 str 在内存中使用的是 Unicode 编码,所以在进行存储和传递的时候要进行转码(使用PyCharm的时候软件已经自行转码了,在自行处理一些 str 数据的时候我们要自行进行转码)
转码 -> 将 str 数据类型 转换为 bytes数据类型(该类型转化出来的只会是 ASCII UTF-8 gbk)从而可以进行存储和传递,且在进行网络传输或通信的时候只能传递通过字符串转码后的bytes类型,然后再对bytes类型进行解码获取传递的数据
bytes类型
对于英文:
str : 表现形式:s = 'alex'
编码方式: 010101010 unicode
bytes :表现形式:s = b'alex'
编码方式: 000101010 utf-8 gbk ……
对于中文:
str :表现形式:s = '中国'
编码方式: 010101010 unicode
bytes :表现形式:s = b'\e91\e91\e01\e21\e31\e32' -> 可以通过查看 b 后面有多少位数就可以判断使用了什么编码方式
编码方式: 000101010 utf-8 gbk ……
- .encode(coding) -> 转码 -> coding : 除了 Unicode 以为的编码 -> 将 str 数据类型 转换为 bytes数据类型
# 英文
se = 'Kevin'
se1 = se.encode('utf-8')
se2 = se.encode('gbk')
se3 = se.encode('ascii')
print(se1, type(se1)) # b'Kevin' <class 'bytes'>
print(se2, type(se2)) # b'Kevin' <class 'bytes'>
print(se3, type(se3)) # b'Kevin' <class 'bytes'>
# 中文
sc = '中文'
sc1 = sc.encode('utf-8')
sc2 = sc.encode('gbk')
print(sc1, type(sc1)) # b'\xe4\xb8\xad\xe6\x96\x87' <class 'bytes'>
print(sc2, type(sc2)) # b'\xd6\xd0\xce\xc4' <class 'bytes'>
# 可以通过查看 b 后面有多少位数就可以判断使用了什么编码方式
# 比如 \xe4\xb8\xad\xe6\x96\x87 有 24 位,则使用了 uft-8
# 比如 \xd6\xd0\xce\xc4 有 16 位,则使用了 gbk
4. 解码 -> 将所转码的字符串解码成Unicode 编码 -> 使用了编码方式转码的就用什么编码方式解码
- .decode(coding) -> 解码 -> coding: 编码方式
- 正常解码
s = '中文解码'
b = s.encode('utf-8') # b'\xe8\xa7\xa3\xe7\xa0\x81'
# byte ---> str decode 解码
s1 = b.decode('utf-8') # 解码
s = 'Python3'
b = s.encode('utf-8') # b'Python3'
# byte ---> str decode 解码
s1 = b.decode('utf-8') # Python3
s = 'Python解码'
b = s.encode('utf-8') # b'Python\xe8\xa7\xa3\xe7\xa0\x81'
# byte ---> str decode 解码
s1 = b.decode('utf-8') # Python解码
- 不正常解码 中文 编码格式为 utf-8 解码格式为 gbk -> 报错
s = '不正常解码'
b = s.encode('utf-8') # b'\xe4\xb8\…………'
# byte ---> str decode 解码
s1 = b.decode('gbk') # 报错
- 不正常解码 英文 编码格式为 utf-8 解码格式为 gbk -> 不会报错,正常输出,因为 utf-8 英文 8位代表1个字符 gbk 也是一样,所以可以正常输出但最好不要这样做
s = 'Python'
b = s.encode('utf-8') # b'Python'
# byte ---> str decode 解码
s1 = b.decode('gbk') # Python
- 不正常解码 中英 编码格式为 utf-8 解码格式为 gbk -> 不会报错,乱码
s = 'Python解码'
b = s.encode('utf-8') # b'Python\xe8\xa7\xa3\xe7\xa0\x81'
# byte ---> str decode 解码
s1 = b.decode('gbk') # Python瑙g爜
- xxx 编码 转 xxx 编码
- gbk 转 utf8 -> 首先要将 gbk 编码 解码(decode)成 Unicode 编码,因为所有的编码都是通过 Unicode 编码衍生出来的,然后再将 Unicode 编码 转成(encode)utf-8 -> 其他转码同理
e_str = 'xxx编码 转 xxx编码'
e_gbk = e_str.encode('gbk') # 如果直接拿到的是 gbk 编码的字符串直接 decode,这里只是为了演示直接转成了 gbk
d_unicode = e_gbk.decode('gbk') # 将 gbk 解码成 unicode 编码
e_utf8 = d_unicode.encode('utf-8') # 通过 unicode 编码 转成 utf-8