Python2和3字符编码的区别

一、字符编码应用之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默认的编码格式。

import sys

sys.getdefaultencoding()
'utf-8'

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

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

#coding:gbk
你好啊

阶段三:读取已经加载到内存的代码(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()方法查看'上'的字符编码。

# 三、Python2中代码

# 四、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。

# 六、Python2中代码

# 七、coding:gbk

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

2.2 Unicode类型

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

# 八、Python2中代码

# 九、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,屌不屌?

2.3 Python3

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

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

如:

#coding:gbk

name = "爸爸"

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

Python2和3字符编码的区别的更多相关文章

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

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

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

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

  3. Python2与Python3字符编码的区别

    目录 字符编码应用之Python(掌握) 执行Python程序的三个阶段 Python2与Python3字符串类型的区别(了解) Python2 str类型 Unicode类型 Python3 字符编 ...

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

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

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

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

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

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

  7. ASCII,Unicode,GBK和UTF-8字符编码的区别和联系

    如果经常写python2,肯定会遇到各种“奇怪”的字符编码问题,每次都通过谷歌解决了,但是为什么会造成这种乱码.decode/encode失败等等,本文就字符和字符编码做一个总结,更加清晰区分诸多的编 ...

  8. ASCII、Unicode、GBK和UTF-8字符编码的区别联系

    转自http://dengo.org/archives/901 很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们看到8个开关状态是好的,于是他们把这称 ...

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

    http://dengo.org/archives/901 这是我看过的最好的一篇讲述编码的文章 很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们看到 ...

随机推荐

  1. Leet Code 2.两数相加

    2.两数相加 题目描述 给出两个非空的链表用来表示两个非负的整数.其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字.如果,我们将这两个数相加起来,则会返回一个新的链表来表 ...

  2. 2019 SDN上机第一次实验作业

    1. 安装轻量级网络仿真工具Mininet 先从GitHub上获取mininet源码,再输入命令进行安装,代码分别如下: git clone https://github.com/mininet/mi ...

  3. (基因功能 & 基因表达调控)研究方案

    做了好久的RNA-seq分析,基因表达也在口头溜了几年了,但似乎老是浮在表面. 对一件事的了解程度决定了你的思维深度,只想做技工就不用想太多,想做大师就一定要刨根问底. 老是说基因表达,那么什么是基因 ...

  4. Win10 设备管理器一个USB设备描述符请求失败解决方法

    问题:进入设备管理器,发现[通用串行总线控制器]下有一项带有黄色[!]未知USB设备(设备描述符请求失败). 或者 解决方法如下: 1.点击Windows键 +R或者(点击系统桌面左下角[开始],在开 ...

  5. 基于 Binlog + Flink 实现多表数据同构/异构方案

    https://mp.weixin.qq.com/s/1h942YAcS6fhO5C43hGX-w 什么是数据异构?简单讲,就是将数据进行异地数据异构存储. 数据异构 服务市场使用 BinLake(京 ...

  6. vue 日历组件

    Github 上很多点击弹出日历选择某个时间的组件,却没有找到单纯展示日历并且能点击获取时间的组件 npm i vue-calendar-component --save cnpm i vue-cal ...

  7. 从Windows转mac遇到的一些坑

    本屌由于运气,分了一台imac来办公,由于以前一直都在用windows,现在用Mac有很多不适应的地方.下面介绍一下Mac与Windows有明显区别的地方: mac与windows鼠标滑轮方向不同. ...

  8. Oracle数据库查看表空间sql语句

    转: Oracle数据库查看表空间sql语句 2018-09-03 15:49:51 兰海泽 阅读数 6212   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出 ...

  9. 算法习题---5.2木块问题(UVa101)

    一:题目 输入n,得到编号为0~n-1的木块,分别摆放在顺序排列编号为0~n-1的位置.现对这些木块进行操作,操作分为四种. .move a onto b:把木块a.b上的木块放回各自的原位,再把a放 ...

  10. spring 使用XML配置开发Spring AOP

      XML方式开发AOP与注解开发原理是相同的,所以这里主要介绍一些用法即可.这里需要在XML中引入AOP的命名空间,所以先来了解一下AOP可配置的元素 代码清单:切面类 package com.ss ...