当前位置: 首页 > news >正文

python之字符编码

字符编码

      了解字符编码的存储知识

计算机基础知识

****应用程序任何操作硬件的请求都需要向操作系统发起系统调用,然后由操作系统操作硬件

     1.计算机运行程序的三大核心硬件

                    cpu--------计算、运行程序                                内存---------存的快,通电存                      硬盘-------永久性保存,读写速度慢      

任何操作的运行都必须先从硬盘中加载到内存,再由cpu到内存调用执行

操作系统的作用:1控制硬件    2.为软件提供系统调用接口

操作系统管理软件,     应用系统通过操作系统间接的操作硬件,如电脑开机,先开机启动操作系统(在硬盘中)然后将操作系统代码加载到内存,再cpu调用执行,操作系统正式启动运行。

  2. 文本编辑器存取文件的原理(nodepad++,pycharm,word)

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

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

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

      3. python解释器执行py文件的原理 ,例如python test.py

    第一阶段:python解释器启动,此时就相当于启动了一个文本编辑器

    第二阶段:python解释器相当于文本编辑器,去打开test.py文件,从硬盘上将test.py的文件内容读入到内存中(小复习:pyhon的解释性,决定了解释器只关心文件内容,不关心文件后缀名)

    第三阶段:python解释器解释执行刚刚加载到内存中test.py的代码( ps:在该阶段,即执行时,才会识别python的语法,执行文件内代码,执行到name="egon",会开辟内存空间存放字符串"egon")

总结:python解释器于文件本编辑的异同

     相同点:python解释器是解释执行文件内容的,因而python解释器具备读py文件的功能,这一点与文本编辑器一样

      不同点:文本编辑器将文件内容读入内存后,是为了显示/编辑,python解释器将文件内容读入内存后,是为了执行(识别python语法)

把人认识的子字符转换为计算机能读懂的二进制数字

字符--------(翻译过程)------->数字 

  这个过程实际就是一个字符如何对应一个特定数字的标准,这个标准称之为字符编码

***(1)一个python文件的内容是有一堆字符组成,存取均涉及到编码问题(python文件并未执行,前两个阶段均属于该范畴)

(2)python中的数据类型字符串是由一串字符组成的(python文件执行时,即第三个阶段)

字符看编码的发展史

电脑只认识01010101这样的数字,(二进制数第一位永远是零)

为了各国都能使用计算机,同一规定了unicode, 统一用2Bytes代表一个字符, 2**16-1=65535,可代表6万多个字符,因而兼容万国语言

1Bytes=8bit,,8bit可以表示0-2**8-1种变化,即可以表示256个字符

最早的字符编码为Ascii,只规定了英文字母数字和一些特殊字符与数字对应关系,最多只能用8位来表示(一个字节),即:2**8=256,所以,Ascll吗最多只能表示256个符号

Ascii码用一个字节(8位二进制)代表一个字符(一个字节表示所有英文,两个字节十六位表示一个中文)

unicode常用2个字节(16位进制)代表一个字符,生僻字需要四个字节(也叫万国码)

国人为了满足中国需求,规定了只有中国能用的GBK,一个中文用两个字节表示

utf-8(升级版):utf-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,一个中文用三个字节表示

四 总结字符编码的发展可分为三个阶段(重要)

复制代码
#阶段一:现代计算机起源于美国,最早诞生也是基于英文考虑的ASCII
ASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256个字符

ASCII最初只用了后七位,127个数字,已经完全能够代表键盘上所有的字符了(英文字符/键盘的所有其他字符),后来为了将拉丁文也编码进了ASCII表,将最高位也占用了

#阶段二:为了满足中文和英文,中国人定制了GBK GBK:2Bytes代表一个中文字符,1Bytes表示一个英文字符 为了满足其他国家,各个国家纷纷定制了自己的编码 日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里 #阶段三:各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。如何解决这个问题呢??? #!!!!!!!!!!!!非常重要!!!!!!!!!!!! 说白了乱码问题的本质就是不统一,如果我们能统一全世界,规定全世界只能使用一种文字符号,然后统一使用一种编码,那么乱码问题将不复存在, ps:就像当年秦始皇统一中国一样,书同文车同轨,所有的麻烦事全部解决 很明显,上述的假设是不可能成立的。很多地方或老的系统、应用软件仍会采用各种各样的编码,这是历史遗留问题。于是我们必须找出一种解决方案或者说编码方案,需要同时满足: #1、能够兼容万国字符 #2、与全世界所有的字符编码都有映射关系,这样就可以转换成任意国家的字符编码  这就是unicode(定长), 统一用2Bytes代表一个字符, 虽然2**16-1=65535,但unicode却可以存放100w+个字符,因为unicode存放了与其他编码的映射关系,准确地说unicode并不是一种严格意义上的字符编码表,下载pdf来查看unicode的详情: 链接:https://pan.baidu.com/s/1dEV3RYp 很明显对于通篇都是英文的文本来说,unicode的式无疑是多了一倍的存储空间(二进制最终都是以电或者磁的方式存储到存储介质中的) 于是产生了UTF-8(可变长,全称Unicode Transformation Format),对英文字符只用1Bytes表示,对中文字符用3Bytes,对其他生僻字用更多的Bytes去存 #总结:内存中统一采用unicode,浪费空间来换取可以转换成任意编码(不乱码),硬盘可以采用各种编码,如utf-8,保证存放于硬盘或者基于网络传输的数据量很小,提高传输效率与稳定性。
复制代码

 

!!!总结非常重要的两点!!!

#1、保证不乱吗的核心法则就是,字符按照什么标准而编码的,就要按照什么标准解码,此处的标准指的就是字符编码

#2、在内存中写的所有字符,一视同仁,都是unicode编码,比如我们打开编辑器,输入一个“你”,我们并不能说“你”就是一个汉字,此时它仅仅只是一个符号,该符号可能很多国家都在使用,根据我们使用的输入法不同这个字的样式可能也不太一样。只有在我们往硬盘保存或者基于网络传输时,才能确定”你“到底是一个汉字,还是一个日本字,这就是unicode转换成其他编码格式的过程了

                  unicode----->encode-------->utf-8

                  utf-8-------->decode---------->unicode

#补充:

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

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

练习题

1、简述bit,byte,kb,MB,GB,TB的关系
关系: # 1bype = 8bit
       1kb = 1024bype
       1MB = 1024kb
       1GB = 1024MB
       1TB = 1024GB

2、简述ascii、unicode、utf-8、gbk的关系
    ascii:只有八位,只能存储单独几个中文,不能储存所有中文。8bit
    unicode:为解决ascii问题创建万国码,一个中文用四个字节表示,2**(4*8)
    utf-8:由于unicode过于浪费创建了一个中文用三个字节表示,是unicode的升级版,可兼容多个国家语言。2**(3*8)
    gbk:只用于中文,一个中文用2个字节表示 2**(2*8)

3、请写出’李杰’分别用utf-8和gbk编码所占的字节及位数。
      李杰:为两个中文字符
            在utf-8中,一个中文字符用3个字节表示,所以有6个字节
            一个字节是8位,6个字节是:48位
            在gbk中,一个中文字符用2个字节表示,所以有2*2=4字节
            一个字节是8位,4个字节是:32

 python2编译安装时,可以通过参数,   --enable-unicode=ucs2 或 --enable-unicode=ucs4分别

用于指定2个字节,4个字节表示一个unicode字符;python3无法进行选择,默认使用ucs4.

       查看当前Python中表示unicode字符串时占用的空间:

       import sys

       print(sys.maxunicode)

      #如果使用 65535,则表示使用ucs2标准,即:2个字节表示

      #如果值是 1114111,则表示使用ucs4标准,即:4个字节

1,ascii:最开始,简单的密码本,八位,最左边都是0

2,万国码,unicode,目前两个版本

     两个字节(16位)表示一个字符,四个(32)字节表示一个字符

    字符:a,我,A,码

3,unicode 升级

utf-8:最少的位数(字节)去表示一个字符,英文字母,1个字节,欧洲有些语言2个字节表示,亚洲:中日韩等,三个字节表示一个字符

gbk:中国特有的:2个字节表示一个字符

Ascii:刚开始是七位,为了扩展最后确定八位,最左边永远为0,八位表示一个字节。

 不同的编码之间不能互相识别,否则会乱码

存储,传输的是utf-8或gbk或unicode

阶段一:启动python解释器

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

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

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

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

 

改正:在test.py指定文件头,字符编码一定要为gbk,

#coding:gbk
你好啊

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

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

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

但是程序在执行过程中,会申请内存(与程序代码所存在的内存是俩个空间)用来存放python的数据类型的值,而python的字符串类型又涉及到了字符的概念

比如x="egon",会被python解释器识别为字符串,会申请内存空间来存放字符串类型的值,至于该字符串类型的值被识别成何种编码存放,这就与python解释器的有关了,而python2与python3的字符串类型又有所不同。 
复制代码

4.2 python2与python3字符串类型的区别

一 在python2中有两种字符串类型str和unicode

str类型

当python解释器执行到产生字符串的代码时(例如x='上'),会申请新的内存地址,然后将'上'编码成文件开头指定的编码格式

要想看x在内存中的真实格式,可以将其放入列表中再打印,而不要直接打印,因为直接print()会自动转换编码,这一点我们稍后再说。

#coding:gbk
x='' y='' print([x,y]) #['\xc9\xcf', '\xcf\xc2'] #\x代表16进制,此处是c9cf总共4位16进制数,一个16进制四4个比特位,4个16进制数则是16个比特位,即2个Bytes,这就证明了按照gbk编码中文用2Bytes
print(type(x),type(y)) #(<type 'str'>, <type 'str'>)

理解字符编码的关键!!!

内存中的数据通常用16进制表示,2位16进制数据代表一个字节,如\xc9,代表两位16进制,一个字节

gbk存中文需要2个bytes,而存英文则需要1个bytes,它是如何做到的???!!!

gbk会在每个bytes,即8位bit的第一个位作为标志位,标志位为1则表示是中文字符,如果标志位为0则表示为英文字符

x=‘你a好’
转成gbk格式二进制位
8bit+8bit+8bit+8bit+8bit=(1+7bit)+(1+7bit)+(0+7bit)+(1+7bit)+(1+7bit)

这样计算机按照从左往右的顺序读:

#连续读到前两个括号内的首位标志位均为1,则构成一个中午字符:你

#读到第三个括号的首位标志为0,则该8bit代表一个英文字符:a

#连续读到后两个括号内的首位标志位均为1,则构成一个中午字符:好

也就是说,每个Bytes留给我们用来存真正值的有效位数只有7位,而在unicode表中存放的只是这有效的7位,至于首位的标志位与具体的编码有关,即在unicode中表示gbk的方式为:

(7bit)+(7bit)+(7bit)+(7bit)+(7bit)

 

按照上图翻译的结果,我们可以去unicode关于汉字的对应关系中去查:链接:https://pan.baidu.com/s/1dEV3RYp

 

可以看到“”上“”对应的gbk(G0代表的是gbk)编码就为494F,即我们得出的结果,而上对应的unicode编码为4E0A,我们可以将gbk-->decode-->unicode

#coding:gbk
x=''.decode('gbk') y=''.decode('gbk') print([x,y]) #[u'\u4e0a', u'\u4e0b']

unicode类型

当python解释器执行到产生字符串的代码时(例如s=u'林'),会申请新的内存地址,然后将'林'以unicode的格式存放到新的内存空间中,所以s只能encode,不能decode

#coding:gbk
x=u'' #等同于 x='上'.decode('gbk') y=u'' #等同于 y='下'.decode('gbk') print([x,y]) #[u'\u4e0a', u'\u4e0b']
print(type(x),type(y)) #(<type 'unicode'>, <type 'unicode'>)

打印到终端

对于print需要特别说明的是:

当程序执行时,比如

x='上' #gbk下,字符串存放为\xc9\xcf

print(x) #这一步是将x指向的那块新的内存空间(非代码所在的内存空间)中的内存,打印到终端,按理说应该是存的什么就打印什么,但打印\xc9\xcf,对一些不熟知python编码的程序员,立马就懵逼了,所以龟叔自作主张,在print(x)时,使用终端的编码格式,将内存中的\xc9\xcf转成字符显示,此时就需要终端编码必须为gbk,否则无法正常显示原内容:上

对于unicode格式的数据来说,无论怎么打印,都不会乱码

unicode这么好,不会乱码,那python2为何还那么别扭,搞一个str出来呢?python诞生之时,unicode并未像今天这样普及,很明显,好的东西你能看得见,龟叔早就看见了,龟叔在python3中将str直接存成unicode,我们定义一个str,无需加u前缀,就是一个unicode,屌不屌?

 

二 在python3 中也有两种字符串类型str和bytes

str是unicode

复制代码
#coding:gbk
x='' #当程序执行时,无需加u,'上'也会被以unicode形式保存新的内存空间中, print(type(x)) #<class 'str'> #x可以直接encode成任意编码格式 print(x.encode('gbk')) #b'\xc9\xcf' print(type(x.encode('gbk'))) #<class 'bytes'>
复制代码

很重要的一点是:看到python3中x.encode('gbk') 的结果\xc9\xcf正是python2中的str类型的值,而在python3是bytes类型,在python2中则是str类型

于是我有一个大胆的推测:python2中的str类型就是python3的bytes类型,于是我查看python2的str()源码,发现

 

转载于:https://www.cnblogs.com/mds---123/p/7230943.html

相关文章:

  • Hadoop计算文件大小
  • 在Oracle中利用SQL_TRACE跟踪SQL的执行
  • Linux添加/删除用户和用户组
  • Hive优化(3)之随机数避免数据倾斜
  • Angular2学习(一)
  • hive优化(4)之mapjoin和union all避免数据倾斜
  • hive cli
  • Hive优化(5)之选择合适的map数
  • C++ 文件操作(CFile类)
  • Hadoop MapReduce:详解Shuffle过程
  • 编译树莓派2代B型OpenWrt固件实现无线路由器及nodogsplash认证功能
  • 为什么一些公司把dwg文件转化为pdf
  • hadoop生态系统
  • influxDB 变换类函数
  • C# Android 开发中使用 Sqlite.NET ORM
  • 分享一款快速APP功能测试工具
  • __proto__ 和 prototype的关系
  • create-react-app项目添加less配置
  • css系列之关于字体的事
  • HomeBrew常规使用教程
  • k8s如何管理Pod
  • Laravel 实践之路: 数据库迁移与数据填充
  • laravel5.5 视图共享数据
  • mysql中InnoDB引擎中页的概念
  • vue-router 实现分析
  • 闭包--闭包之tab栏切换(四)
  • 测试如何在敏捷团队中工作?
  • 利用DataURL技术在网页上显示图片
  • 猫头鹰的深夜翻译:Java 2D Graphics, 简单的仿射变换
  • 前端之Sass/Scss实战笔记
  • 王永庆:技术创新改变教育未来
  • 小而合理的前端理论:rscss和rsjs
  •  一套莫尔斯电报听写、翻译系统
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • #预处理和函数的对比以及条件编译
  • (8)STL算法之替换
  • (done) 两个矩阵 “相似” 是什么意思?
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • . Flume面试题
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .Net Redis的秒杀Dome和异步执行
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .Net下的签名与混淆
  • @Async注解的坑,小心
  • @DataRedisTest测试redis从未如此丝滑
  • @Import注解详解