一、字符编码应用之Python

1.1 执行Python程序的三个阶段

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

test.py文件内容以gbk格式保存的,内容为:

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

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

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

  1. import sys
  2. sys.getdefaultencoding()
  1. 'utf-8'

Python2中默认使用ascii,Python3中默认使用utf-8。

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

  1. #coding:gbk
  2. 你好啊

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

内存的编码使用Unicode,不代表内存中全都是Unicode,因为在程序执行之前,内存中确实都是Unicode,比如从文件中读取了一行name="nick",其中的name、等号、引号的地位都一样,都是普通字符而已,都是以Unicode的格式存放于内存中的。

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

比如name="nick",会被Python解释器识别为字符串,会申请内存空间来存放字符串类型的值,至于该字符串类型的值被识别成何种编码存放,这就与Python解释器的有关了,而Python2与Python3的字符串类型又有所不同。

二、Python2与Python3字符串类型的区别

2.1 Python2

在Python2中有两种字符串类型str和Unicode。

2.1.1 str类型

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

因为直接print()会自动转换编码,我们使用encode()方法查看'上'的字符编码。

  1. # 三、Python2中代码
  2. # 四、coding:gbk
  3. x = '上'
  4. y = '下'
  5. print([x, y]) # ['\xc9\xcf', '\xcf\xc2']
  6. # 五、\x代表16进制,此处是c9cf总共4位16进制数,一个16进制四4个比特位,4个16进制数则是16个比特位,即2个Bytes,这就证明了按照gbk编码中文用2Bytes
  7. 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. 连续读到前两个括号内的首位标志位均为1,则构成一个中午字符:你
  2. 读到第三个括号的首位标志为0,则该8bit代表一个英文字符:a
  3. 连续读到后两个括号内的首位标志位均为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。

  1. # 六、Python2中代码
  2. # 七、coding:gbk
  3. x = '上'.decode('gbk')
  4. y = '下'.decode('gbk')
  5. print([x, y]) # [u'\u4e0a', u'\u4e0b']

7.0.2 Unicode类型

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

  1. # 八、Python2中代码
  2. # 九、coding:gbk
  3. x = u'上' # 等同于 x='上'.decode('gbk')
  4. y = u'下' # 等同于 y='下'.decode('gbk')
  5. print([x, y]) # [u'\u4e0a', u'\u4e0b']
  6. 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,屌不屌?

9.1 Python3

Python3中str都是Unicode编码的,所以Python3中的str类型的数据可以编码成其他字符编码的格式,编码的结果为bytes类型。

  1. # coding:gbk
  2. x = '上' # 当程序执行时,无需加u,'上'也会被以Unicode形式保存新的内存空间中,
  3. print(f"type(x): {type(x)}") # <class 'str'>
  4. # x可以直接encode成任意编码格式
  5. print(f"x.encode('gbk'): {x.encode('gbk')}") # b'\xc9\xcf'
  6. print(f"type(x.encode('gbk')): {type(x.encode('gbk'))}") # <class 'bytes'>
  1. type(x): <class 'str'>
  2. x.encode('gbk'): b'\xc9\xcf'
  3. type(x.encode('gbk')): <class 'bytes'>

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

总而言之

代码详情 Python2执行情况 Python3执行情况
# coding:gbk
print('中')
终端:utf8
乱码 不乱码
# coding:utf8
print('中')
终端:utf8
不乱码 不乱码
# coding:gbk
print(u'中')
终端:utf8
不乱码 不乱码
# coding:utf8
print(u'中')
终端:utf8
不乱码 不乱码

在Python2中如果指定了字符编码,那么内存存取就会按照指定的字符编码去入内存。解释或去执行时就要按照指定了的字符编码去解释,否则就会乱码。 否则可以在定义变量前面加上u,这样变量就会以unicode编码存入内存。

如:

  1. #coding:gbk
  2. name = "爸爸"

但在Python3中就不会有这样的问题,因为无论你指定了什么字符编码,在内存存取时都会使用Unicode编码去入内存,Unicode编码可以和任意的字符编码相互转换,并在读取时按照所需的编码区读取,这样就很好解决了字符编码的问题

Python2与Python3字符编码的区别的更多相关文章

  1. day008 字符编码之 字符编码 、Python2和Python3字符编码的区别

    计算机基础(掌握) 启动应用程序的流程 双击qq 操作系统接受指令然后把该操作转化为0和1发送给CPU CPU接受指令然后把指令发送给内存 内存接受指令把指令发送给硬盘获取数据 qq在内存中运行 文本 ...

  2. Python2和3字符编码的区别

    Python2和3字符编码的区别 一.字符编码应用之Python 1.1 执行Python程序的三个阶段 Python test.py(我再强调一遍,执行test.py的第一步,一定是先将文件内容从硬 ...

  3. 第六篇.文件处理之python2和3字符编码的区别

    目录 python2和3字符编码的区别 一.字符编码应用之python python2和3字符编码的区别 一.字符编码应用之python 1执行python的三个阶段 python test.py 执 ...

  4. 50-Python2和3字符编码的区别

    目录 Python2和3字符编码的区别 python2 python3 Python2和3字符编码的区别 区别点 python2 python3 print 是一个语法结构 是一个函数,print(' ...

  5. 字符编码 + python2和python3的编码区别(day08整理)

    目录 昨日回顾 二十三.元组内置方法 二十四.散列表 二十五.字典内置方法 二十六.集合内置方法 二十七.深浅拷贝 拷贝 浅拷贝 深拷贝 今日内容 二十八.字符编码 1.文本编辑器存储信息的过程 2. ...

  6. Python2.7 中文字符编码 & Pycharm utf-8设置、Unicode与utf-8的区别

    Python2.7 中文字符编码 & Pycharm utf-8设置.Unicode与utf-8的区别 zoerywzhou@163.com http://www.cnblogs.com/sw ...

  7. python2与python3 字符问题以及 字符编码 内容总结

    python2与python3默认编码: python2:gbk                   print( u'上' )     操作系统也是 gbk    python3:unicode p ...

  8. Python2和Python3的一些语法区别

    Python2和Python3的一些语法区别 python 1.print 在版本2的使用方法是: print 'this is version 2 也可以是 print('this is versi ...

  9. ASCII、Unicode、GBK和UTF-8字符编码的区别联系(转载)

    ASCII.Unicode.GBK和UTF-8字符编码的区别联系 转载自:http://dengo.org/archives/901 很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同 ...

随机推荐

  1. Java面向对象进阶篇(内部类)

    一. 概念 大部分时候,类被定义成一个独立的程序单元.有时候把一个类放在另一个类内部定义,这个类被称为内部类,包含内部类的类也被称为外部类. 内部类的主要作用: 内部类提供良好的封装,可以把内部类隐藏 ...

  2. 在Java中谈尾递归--尾递归和垃圾回收的比较(转载)

    我不是故意在JAVA中谈尾递归的,因为在JAVA中谈尾递归真的是要绕好几个弯,只是我确实只有JAVA学得比较好,虽然确实C是在学校学过还考了90+,真学得没自学的JAVA好 不过也是因为要绕几个弯,所 ...

  3. 开发自己的 chart - 每天5分钟玩转 Docker 容器技术(167)

    Kubernetes 给我们提供了大量官方 chart,不过要部署微服务应用,还是需要开发自己的 chart,下面就来实践这个主题. 创建 chart 执行 helm create mychart 的 ...

  4. jmeter接口测试报java.net.SocketException: Socket closed错误。

    如题,jmeter报出java.net.SocketException: Socket closed,我查询了下,服务器是正常的,可以返回数据,基本确定问题出在我这边jmeter.查询原因,看到有人说 ...

  5. USB/GPIO/SDIO

    通用串行总线(英语:Universal Serial Bus,缩写:USB)是连接计算机系统与外部设备的一种串口总线标准,也是一种输入输出接口的技术规范.它只有4根线,两个电源(5V,地线),两个数据 ...

  6. SVN 使用方法

    svn co http://路径(目录或文件的全路径) [本地目录全路径] --username 用户名 --password 密码svn co svn://路径(目录或文件的全路径) [本地目录全路 ...

  7. datePicker.js 应用

    var calendar2 = new datePicker();calendar.init({ 'trigger': '#datetime-picker-start', /*选择器,触发弹出插件*/ ...

  8. 对混合数值,字符,null的字段进行排序

    今天有个需求是进行排序.  这一列值是字符串类型的, 但是里面有数值型 比如"1" 和null类型的.  实现效果是需要 数值型的先按照数值的方式先排,然后字符串按照字符传排,最后 ...

  9. 什么是设计思维Design Thinking——风靡全球的创造力培养方法

    “把学习带到现实中,让孩子用自己的力量创造改变,可以直接提升他们的幸福感和竞争力.” 这是“全球孩童创意行动”的发起人——Kiran Sethi在TED演讲时说的一句话,这个行动旨在引导中小学生主动寻 ...

  10. 五种开源协议(GPL,LGPL,BSD,MIT,Apache)介绍

    商业化的软件应该主要选用MIT或者Apache license的开源系统作为插件. 什么是许可协议? 什么是许可,当你为你的产品签发许可,你是在出让自己的权利,不过,你仍然拥有版权和专利(如果申请了的 ...