python 字符编码

1、了解字符编码的知识储备。编辑器和终端中所有显示的内容都属于内存,内存使用的unicode

          打开编辑器就打开了启动了一个进程,是在内存中的,所以在编辑器编写的内容也都是存放与内存中的,断电后数据丢失

             因而需要保存到硬盘上,点击保存按钮,就从内存中把数据刷到了硬盘上。

             在这一点上,我们编写一个py文件(没有执行),跟编写其他文件没有任何区别,都只是在编写一堆字符而已。

 

2、字符编码,将字符转化为数字的功过称之为编码

阶段一:现代计算机起源于美国,最早诞生也是基于英文考虑的ASCII

  ASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256个字符

    ASCII最初只用了后七位,127个数字,已经完全能够代表键盘上所有的字符了(英文字符/键盘的所有其他字符)

    后来为了将拉丁文也编码进了ASCII表,将最高位也占用了

阶段二:为了满足中文,中国人定制了GBK

  GBK:2Bytes代表一个字符

  为了满足其他国家,各个国家纷纷定制了自己的编码

  日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr

阶段三:各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。

于是产生了unicode, 统一用2Bytes代表一个字符, 2**16-1=65535,可代表6万多个字符,因而兼容万国语言

但对于通篇都是英文的文本来说,这种编码方式无疑是多了一倍的存储空间(二进制最终都是以电或者磁的方式存储到存储介质中的)

于是产生了UTF-8,对英文字符只用1Bytes表示,对中文字符用3Bytes

需要强调的一点是:

unicode:简单粗暴,所有字符都是2Bytes,优点是字符->数字的转换速度快,缺点是占用空间大

utf-8:精准,对不同的字符用不同的长度表示,优点是节省空间,缺点是:字符->数字的转换速度慢,因为每次都需要计算出字符需要多长的Bytes才能够准确表示

  1. 内存中使用的编码是unicode,用空间换时间(程序都需要加载到内存才能运行,因而内存应该是尽可能的保证快)
  2. 硬盘中或者网络传输用utf-8,网络I/O延迟或磁盘I/O延迟要远大与utf-8的转换延迟,而且I/O应该是尽可能地节省带宽,保证数据传输的稳定性。

无论是何种编辑器,要防止文件出现乱码
核心法则就是,文件以什么编码保存的,就以什么编码方式打开
而文件编码保存时候使用的编码方式是右下角的编码方式,而解码的时候是使用文档开头申明的编码方式,两种编码不同的时候很容易出现乱码的情况。

 

3、执行程序

python test.py   (我再强调一遍,执行test.py的第一步,一定是先将文件内容读入到内存中)

阶段一:启动python解释器

阶段二:python解释器此时就是一个文本编辑器,负责打开文件test.py,即从硬盘中读取test.py的内容到内存中

此时,python解释器会读取test.py的第一行内容,#coding:utf-8,来决定以什么编码格式来读入内存,这一行就是来设定python解释器这个软件的编码使用的编码格式这个编码,

可以用sys.getdefaultencoding()查看,如果不在python文件指定头信息#-*-coding:utf-8-*-,那就使用默认的

python2中默认使用ascii,python3中默认使用utf-8

阶段三:读取已经加载到内存的代码(unicode编码的二进制),然后执行,执行过程中可能会开辟新的内存空间,比如x="egon"

内存的编码使用unicode,不代表内存中全都是unicode编码的二进制,

在程序执行之前,内存中确实都是unicode编码的二进制,比如从文件中读取了一行x="egon",其中的x,等号,引号,地位都一样,都是普通字符而已,都是以unicode编码的二进制形式存放与内存中的

但是程序在执行过程中,会申请内存(与程序代码所存在的内存是俩个空间),可以存放任意编码格式的数据,比如x="egon",会被python解释器识别为字符串,会申请内存空间来存放"hello",然后让x指向该内存地址,此时新申请的该内存地址保存也是unicode编码的egon,如果代码换成x="egon".encode('utf-8'),那么新申请的内存空间里存放的就是utf-8编码的字符串egon了

针对python3如下图

 

浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器

 

如果服务端encode的编码格式是utf-8, 客户端内存中收到的也是utf-8编码的二进制。

 

4、python2与python3的区别

Python3  str类型 和bytes

# Author : xiajinqi
#  _*_ coding:utf8 _*_
# python3 中默认以uncode
str1 = '刘亦菲'  #python3 当程序执行时,无需加u,'林'也会被以unicode形式保存新的内存空间中,
str2= u'刘亦菲'  #
print (type(str1),type(str2))
print(str1,str2)  #程序执行时候,str1,str2申请以unicode格式编码存储在内存空间张,打印终端也属于内存。相当于从内存到内存,只是空间不同而已,编码一直。因此永远不会乱码,并且不可以decode

str3 =str1.encode('utf-8')   #字符串以utf8编码转化为字节类型,存储在内存空间
str4 =str1.encode('gbk')   #字符串以utf8编码转化为字节类型,存储在内存空间
print(str3,str4)   #


E:\Users\xiajinqi\PycharmProjects\twoday\venv\Scripts\python.exe E:/Users/xiajinqi/PycharmProjects/twoday/coding.py
<class 'str'> <class 'str'>
刘亦菲 刘亦菲
b'\xe5\x88\x98\xe4\xba\xa6\xe8\x8f\xb2' b'\xc1\xf5\xd2\xe0\xb7\xc6'

Process finished with exit code 0


Python2 str类型 和bytes

str1 = '刘亦菲'  #python3 当程序执行时,''也会被以python文件开头指定的字符编码进行编码形式保存新的内存空间中,因此只能decode 与python存在很大差异
str2= u'刘亦菲'  #

#coding:utf-8
s=u'' #当程序执行时,''会被以unicode形式保存新的内存空间中


#s指向的是unicode,因而可以编码成任意格式,都不会报encode错误
s1=s.encode('utf-8')
s2=s.encode('gbk')
print s1 #打印正常否?
print s2 #打印正常否


print repr(s) #u'\u6797'
print repr(s1) #'\xe6\x9e\x97' 编码一个汉字utf-8用3Bytes
print repr(s2) #'\xc1\xd6' 编码一个汉字gbk用2Bytes

print type(s) #<type 'unicode'>
print type(s1) #<type 'str'>
print type(s2) #<type 'str'>

总结:python3 和python2中的变量u都是以uncode编码。因此无能如何打印,终端不会出现乱码(因为终端是属于内存,因此也是用uncode)。

 

 




 

posted @ 2018-04-07 16:02  马里亚纳仰望星空  Views(198)  Comments(0Edit  收藏  举报