编码
基本上是一个共同需要面对的问题,不管你用什么语言,之前面试被问到过几次,一直回答的似懂非懂,这回来统一整理一下。
1. 发展历程
1.1 概念普及
1字节(Byte) = 8bit
任何字符(实际的文字符号)表达的最小单位是字节。
字符编码又叫做字集码,编码就是
将字符集中的字符映射为一个唯一二进制的过程
简而言之:
编码是给计算机看的,解码是给人看的
1.2 背景
没有什么东西再刚被创造出来时就是普适的,一开始的字符也只包括了26个英文字母,加上数字,一些符号,控制字符……总数也不多,一个字节就可以表示全了。这就是Ascii编码(American Standard Code for Information Interchange,美国信息互换标准代码)。
然而编程传入中国后,汉字太多,一个字节不够用了,于是中国人就定了一个GB 2312(中国国家标准简体中文字符集),用两个字节表示一个字符,第一个字节叫高字节,二个叫低字节,而且对低字节加了限制。当然同时也保持了对Ascii的兼容。
但是后来发现这个低字节的限制的有点狠了,又不够用了,于是放宽低字节的限制,产生了GBK(即汉字内码扩展规范),接下来又考虑到了少数民族的语言文化,以及其他汉字国家的文字,出现了GB13080。同样保持着向下兼容的同时,GB13080采用单字节,双字节,四字节的方式编码。
然而不止中国这么干啊,每个有着自己的的语言的国家都弄这么几套编码,大大增加了跨国编程的难度,于是ISO(国际标准化组织)弄了个统一的标准,”Universal Multiple-Octet Coded Character Set”,简称 UCS, 俗称 “unicode”。
1.3 unicode
现在提到了unicode,但是unicode是表现形式而不是存储形式,具体的编码规则叫做UTF(UCS Transfer Format)。
也就是说unicode是飘在空中的一个规范,具体落地要转化成utf-8,utf-16,gbk……它们才是一个层次的。
2. 在Python中的应用
2.1 Python2.7
py2中的“字符串”类型分为两种:str和unicode。
其中unicode一定是unicode编码,str可能是utf-8,ascii,gbk……
其实更准确的来说str应该是“字节串”而不是“字符串”,即每个字节算一个单位长度。
ok,talk is cheap,show me the code
s = "严"
len(s) => 3
type(s) => str
us = u"严"
len(us) => 1
type(us) => unicode
Python中用encode()和decode()来进行编码和解码,unicode作为中间类型:
decode encode
str ---------> unicode ---------> str
找一段现成的代码。。
>>> us = u'严'
>>> ss = us.encode('utf-8')
>>> ss
'\xe4\xb8\xa5'
>>> type(ss)
<type 'str'>
>>> ss.decode('utf-8') == us
True
如果单纯的指定s="严"
,具体s的存储方式取决于你所用的操作系统的默认编码
import locale
locale.getdefaultlocale()
2.2 Python3
其实我是没怎么用过py2的……毕竟不是学这方面的,大学快毕业了才自学的py,那时候基本上py3已经开始有市场了。
py3中的str已经是真正的“字符串”了,可以理解为它和unicode合二为一,另外新增了一个bytes类。
再找个栗子:
a = '你好'
b = u'你好'
c = '你好'.encode('gbk')
print(type(a),len(a)) # output:<class'str'> 2
print(type(b),len(b)) # output:<class'str'> 2
print(type(c),len(c)) # output:<class'bytes'> 4
具体的转化:
sb = b'aaaaa'
s = sb.decode()
sb = s.encode() # 默认为utf-8