首页 > 代码库 > 字符编码
字符编码
1、关于Python解释器
- 文本编辑器存取文件的原理,比如我们新建一个a.py文件
- 打开编辑器就像打开了一个进程,在内存中运行,所以编辑器内的内容也是在内存中的具有易失性,当你点击点击保存,就是把编辑的内容刷到硬盘上了,这时候,a.py文件就相当于普通文件,都是一堆字符而已
Python解释器执行py文件的原理
- 第一步:Python解释器首先启动,相当于启动了一个文件编辑器
- 第二步:Python解释器去硬盘上把a.py文件再刷到内存中,
- 第三步:Python解释器解释执行刚刚加载到内存中的a.py文件
小结:Python解释器是解释执行文件内容的,而文本编辑器只能读文件,不能执行
2、什么是字符编码
计算机只能识别高电频1和低电频0,我们该如何让我们自己认识的文件让计算机认识呢,我们必须让我们的每个字符都有一个特定数字标准来让计算机识别,这个标准就是字符编码
3、字符编码的发展史
- 阶段一,首先是美国搞得,基于英文考虑的ASCLL:一个Bytes代表一个字符(英文字符/键盘上的所有的字符),因为1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256个字符,ASCII最初只用了后七位,127个数字,已经完全能够代表键盘上所有的字符了(英文字符/键盘的所有其他字符)后来为了将拉丁文也编码进了ASCII表,将最高位也占用了
- 阶段二:为了让计算机识别中文,中国人定制了GBK,日本人也编写了Shift_JIS,韩国也编写了。。。。
- 阶段三:这样下去,各国由各国的标准,肯定会有冲突,在多语言的文本中,显示就会有乱码,为了解决这个问题,于是就产生了unicode,统一用2Bytes代表一个字符, 2**16-1=65535,可代表6万多个字符,因而兼容万国语言但对于通篇都是英文的文本来说,这种编码方式无疑是多了一倍的存储空间(二进制最终都是以电或者磁的方式存储到存储介质中的)于是产生了UTF-8,对英文字符只用1Bytes表示,对中文字符用3Bytes
小结:
- nuicode:相对简单粗暴,所有字符都是2Bytes,优点是字符-->数字的转换速度快,缺点是占用空间大
- utf-8:精准,对不同的字符用不同的长度表示,优点是节省空间,缺点是:字符->数字的转换速度慢,因为每次都需要计算出字符需要多长的Bytes才能够准确表示
内存中使用的编码是unicode,用空间换时间,因为程序都要在内存中运行,所以,内存“快”才是第一位,硬盘或者网络传输用的是utf-8,这样是为了保证数据传输稳定性,在传输过程中,还要尽量节省带宽至于utf-8的转换延迟,要小于网络延迟或硬盘I/O延迟。
内存与硬盘的I/O操作
浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器:如果服务端encode的编码格式是utf-8, 客户端内存中收到的也是utf-8编码的二进制。
小结:
无论是何种编辑器,要防止文件出现乱码(请一定注意,存放一段代码的文件也仅仅只是一个普通文件而已,此处指的是文件没有执行前,我们打开文件时出现的乱码),核心法则就是,文件以什么编码保存的,就以什么编码方式打开
Python2和Python3的区别
- 在Python2中有两种字符类型str和Unicode
str类型
当python解释器执行到产生字符串的代码时(例如s=‘林‘),会申请新的内存地址,然后将‘林‘encode成文件开头指定的编码格式,这已经是encode之后的结果了,所以s只能decode
1 #_*_coding:gbk_*_ 2 #!/usr/bin/env python 3 4 x=‘林‘ 5 # print x.encode(‘gbk‘) #报错 6 print x.decode(‘gbk‘) #结果:林
重点:
在python2中,str就是编码后的结果bytes,str=bytes,所以在python2中,unicode字符编码的结果是str/bytes
#coding:utf-8 s=‘林‘ #在执行时,‘林‘会被以conding:utf-8的形式保存到新的内存空间中 print repr(s) #‘\xe6\x9e\x97‘ 三个Bytes,证明确实是utf-8 print type(s) #<type ‘str‘> s.decode(‘utf-8‘) # s.encode(‘utf-8‘) #报错,s为编码后的结果bytes,所以只能decode
unicode类型
当python解释器执行到产生字符串的代码时(例如s=u‘林‘),会申请新的内存地址,然后将‘林‘以unicode的格式存放到新的内存空间中,所以s只能encode,不能decode
s=u‘林‘ print repr(s) #u‘\u6797‘ print type(s) #<type ‘unicode‘> # s.decode(‘utf-8‘) #报错,s为unicode,所以只能encode s.encode(‘utf-8‘)
当打印到终端时
对于print需要特别说明的是:
当程序执行时,比如
x=‘林‘
print(x) #这一步是将x指向的那块新的内存空间(非代码所在的内存空间)中的内存,打印到终端,而终端仍然是运行于内存中的,所以这打印可以理解为从内存打印到内存,即内存->内存,unicode->unicode
对于Unicode格式的数据来说,无论怎么打印,都不会出现乱码
python3中的字符串与python2中的u‘字符串‘,都是unicode,所以无论如何打印都不会乱码
但是在python2中存在另外一种非unicode的字符串,此时,print x,会按照终端的编码执行x.decode(‘终端编码‘),变成unicode后,再打印,此时终端编码若与文件开头指定的编码不一致,乱码就产生了
因为:
在pycharm中(终端编码为utf-8,文件编码为utf-8,不会乱码)
而在Windows终端
在windows终端(终端编码为gbk,文件编码为utf-8,乱码产生)
- 在Python3中也有两种字符串类型str和bytes
str是unicode
#coding:utf-8 s=‘林‘ #当程序执行时,无需加u,‘林‘也会被以unicode形式保存新的内存空间中, #s可以直接encode成任意编码格式 s.encode(‘utf-8‘) s.encode(‘gbk‘) print(type(s)) #<class ‘str‘>
bytes是bytes
#coding:utf-8 s=‘林‘ #当程序执行时,无需加u,‘林‘也会被以unicode形式保存新的内存空间中, #s可以直接encode成任意编码格式 s1=s.encode(‘utf-8‘) s2=s.encode(‘gbk‘) print(s) #林 print(s1) #b‘\xe6\x9e\x97‘ 在python3中,是什么就打印什么 print(s2) #b‘\xc1\xd6‘ 同上 print(type(s)) #<class ‘str‘> print(type(s1)) #<class ‘bytes‘> print(type(s2)) #<class ‘bytes‘>
字符编码