在此之前,我们先简单了解一下编码。
因为计算机只能处理数字,如果要处理文本等,那么必须要把文本转化为二进制的数字才可以处理,最开始只有127个字符被编码计算机里,包括大小写字母,符号,数字,就是美国人用的这些就够了,这套编码表叫做ASCII编码,就是用一个字节编码一个字符,一个字节8位,但是后来呢,由于要加入各种语言,比如中文,日文,韩文等,就不够用了,中文需要用2个字节,所以中国就制订了GB2312规则,把中文加了进去,但是这样肯定不可以的,世界就不统一了,我们写好的文章放到其他国家的计算机里就乱码了呀,这样不行的。
于是,Unicode应运而生,它把所有语言统一到一套编码里,这样就不会有乱码问题了。ascii一个字节,Unicode通常2个字节,因为一些生僻字可能需要3或者4个字节
所以说Unicode编码也是一种编码规则,编码表。
再说一下我们写代码时通常前面会声明一下 UTF-8,这个UTF-8是啥?当我们用中文的时候,是用了2个字节,但是当你在unicode编码下用字母呢,其实只是用了一个字节,就是后面的一个字节,比如 00000000 01000000 ,大家会注意这里就造成了浪费,就是在原来的字节前面加0就可以了,这样就相当于多了一倍的储存空间,在存储和运输上不太划算。
于是,又出现了一个基于Unicode编码的可变长度的UTF-8编码,它把Unicode编码根据不同的数字大小编码成1-6个字节,常用的字母就是一个字节,汉字等通常2-3个字节,这里我们可以注意到,ASCII码其实是可以看成是UTF-8码的一部分,因为当传输英文数字时,长度也是一个字节,和ASCII一样的,这样,很多遗留的历史ASCII问题就可以用UTF-8编码解决了。
现在我们看一下计算机通用的字符编码工作模式:
在计算机内存中,用的是Unicode编码,当要存储在硬盘或者传输时,就转换为UTF-8模式,当我们在编辑一个文本文件时,还没保存的时候,我们用的就是Unicode编码,当我们点击保存时,这时候就转换为UTF-8编码了,当我们读取的时候,就又变成了Unicode编码,就是这样转换的。
在Python3中,字符串str就是以Unicode编码格式编码的,也就是说,Python的字符串可以包括多语言,比如 ‘asd’ 和 ‘六角恐龙’ 都是可以显示的,不会乱码。
Python提供 ord函数获取字符的整数表示,用char函数转换整数到字符格式 ord('A') = 65 char(65) = 'A'
python的字符串类型是str,在内存里以Unicode编码表示,当存储在硬盘时,就要转换为字节为单位的bites,Python对于bites类型的数据用带‘b‘前缀的单引号活双引号表示。
x = b'asd' 这是bite类型的数据,可以看下面的例子,
# -*- coding: utf-8 -*- print ('asd'.encode('ascii')) print(b'asd'.decode('ascii')) print(b'asdsf'.decode('utf-8')) #print('中'.encode('ascii')) 会报错,因为中文不能用ascii码来编码 print('中'.encode('utf-8'))
输出:
b'asd'
asd
asdsf
b'\xe4\xb8\xad'
所以我们在编写程序的时候,一定要把编码和解码放在界面的最外围来做,程序的核心部分应该使用Unicode编码来做,这种办法可以令程序可以接受多种类型的文本编码,并输出的时候只采用一种编码,就是UTF-8编码。
我们最好写2个辅助函数,以便在这两种情况下转换,是的转换后的数据能够符合我们的预期。
Python3 中,我们需要编写接受str或者bites,并只返回str或者bites的函数
只返回str;
# -*- coding: utf-8 -*- def return_only_str(str_or_bytes): if isinstance(str_or_bytes,bytes): ret = str_or_bytes.decode('utf-8') else: ret = str_or_bytes return ret print(type('asd')) print(return_only_str('asd')) print(type(b'asdasd')) print(return_only_str(b'asdasd'))
输出:
<class 'str'>
asd
<class 'bytes'>
asdasd
只返回bytes:
# -*- coding: utf-8 -*- def return_only_byte(str_or_bytes): if isinstance(str_or_bytes,str): ret = str_or_bytes.encode('utf-8') else: ret = str_or_bytes return ret print(type('asd')) print(return_only_byte('asd')) print(type(b'asdasd')) print(return_only_byte(b'asdasd'))
输出:
<class 'str'>
b'asd'
<class 'bytes'>
b'asdasd'
另外Python3还需要注意一个问题,就是当我们使用file函数,file open read等,都是从硬盘里来读文件的操作,我们之前说过的,数据是以二进制的bytes存储的。而Python3的open函数添加了名为encodeing的新参数,而这个新参数的默认值为utf-8,这样在文件句柄上进行write 和 read时,系统就要求开发者必须传入包含unocode的str实例,而不是二进制的bytes实例,这样就会发生错误,就是说我们在以str的格式向硬盘里写数据,这样是不行的,计算机是不认识的。
所以我们要这样来写
with open(file,'wb') as f : 这里的b指的是以2进制的格式来写, 来读文件的时候也是一样的, ‘rb’