一、字符编码应用之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. 连续读到前两个括号内的首位标志位均为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。

# 六、Python2中代码

# 七、coding:gbk

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

7.0.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,屌不屌?

9.1 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与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. CSS后代选择器“空格”和“>”的使用辨析

    要点: 1. "空格":包含子孙 2. ">":含子不含孙 举个栗子: html代码如下 <body> <div class=" ...

  2. asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析

    下面我用一个实例来和大家分享一下我的经验,asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析. using Newtonsoft.Json; usin ...

  3. 44.1khz 16位比特双声道一分钟的音乐文件占多少硬盘空间?

    2*2*44.1*1000*60=10584000字节=10M2个声道*(16比特/8比特)字节*采样率(每秒采样44.1*1000次)*一分钟有60秒16比特是精度,描述振幅的,16比特等于2个字节 ...

  4. HTML 返回顶部

    每次看淘宝,看微信,都回有回到顶部的小logo,小图标,或者双击返回顶部.所以就学习了如何返回顶部的操作,一开始是联想html中的链接描点,在开头出设置个标签,下面点击另外一个标志回去.有三种觉得比较 ...

  5. ScalaPB(4): 通用跨系统protobuf数据,sbt设置

    我们知道,在集群环境节点之间进行交换的数据必须经过序列化/反序列化处理过程,而在这方面protobuf是一个比较高效.易用的模式.用户首先在.proto文件中用IDL来定义系统中各种需要进行交换的数据 ...

  6. 嵌入Python系列 | 调用Python模块中无参数函数

    开发环境 Python版本:3.6.4 (32-bit) 编辑器:Visual Studio Code C++环境:Visual Studio 2013 需求说明 在用VS2013编写的Win32程序 ...

  7. Mac--Homebrew简介及安装

    Homebrew官网:https://brew.sh/index_zh-cn.html 参考:http://www.jianshu.com/p/d229ac7fe77d 关于Homebrew Mac ...

  8. Oracle数据库查询优化方案(处理上百万级记录如何提高处理查询速度)

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引.2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引 ...

  9. Ajax 与服务器通信 验证编号重复

    在最近的一个Web项目中,需要实现一个功能,就是用户在前端输入一个编号,后台需要验证这个编号是否在数据库中已经存在,如果存在就提示用户. 主要用到两个模块.第一:在jsp中添加一个脚本,利用ajax向 ...

  10. java处理图片--图片的缩放,旋转和马赛克化

    这是我自己结合网上的一些资料封装的java图片处理类,支持图片的缩放,旋转,马赛克化.(转载请注明出处:http://blog.csdn.net/u012116457) 不多说,上代码: packag ...