第一章:计算机通论---编程与编码
1.1 计算机通论
人类自身的计算能力有限,遇到复杂的问题,仅仅依靠人脑非常难以解决或者要耗费非常长的时间才能解决,针对复杂的计算问题,人类就依赖于机器去完成,故此产生了计算机;----计算机诞生;
计算机是电气设备,其在底层仅仅只有两种状态:有电/无电;即高低电平,高电平标识有电,而低电平标识无电;我们将高低电平采用数字01标识,即产生了计算机能够识别的二进制代码---机器码;
计算机仅仅具有的计算能力,而不具备逻辑思维能力(只有人才有逻辑思维能力),即计算机仅仅只能实现计算,而不具备思考如何进行计算解决问题;计算机的计算能力,即对计算机识别的二进制代码的进行位运算的能力;针对计算机的此种特性,人类想要依靠计算机去解决自己遇到的问题,必须有两个必要的条件:
条件一:人类必须告诉计算机如何去解决问题,即解决问题的逻辑--------引入编程;
编程即是通过程序代码指示计算机如何进行计算,解决问题;
条件二:人类教给计算机的逻辑,要能让计算机能够识别并理解----------编码;
编码即程序代码要能让计算机能够识别和理解,只有识别和理解之后计算机才知道如何进行运算;
总结:
编程是依赖于编码实现的,因为,编程是人类教给计算机解决问题的逻辑,此时必须要以计算机能够理解的语言去让计算机进行运算;故此引入了编程和编码的概念;
1.2 编码通论
1.2.1 发展
stage1:人类适应机器
早期人类采用二进制的方式去编程;人类借助于计算机能够识别的二进制而进行编程,告诉计算机解决问题的逻辑,计算机按照程序指定的逻辑应用自己的计算能力,解决了类遇到的问题;
优点: 计算机能够完美的解决人类遇到的问题;
缺点: 二进制编程非常复杂,人不容易掌握,故此真正实现二进制编程非常复杂;
stage2: 机器适应人类
为了解决二进制编程复杂且不易掌握的问题,而直接采用人类自身的自然语言进行编程,采用自然语言进行编程,虽然容易掌握,且非常适合开发,但是人类自身的语言机器不能理解和识别;如何让计算机识别人类的自然语言编写的程序代码成为了新的问题,故此产生了编码;
1.2.2 编码
目标:
计算机语言和人类的语言能够相互识别,实现交互;
底层原理:
不同的编码方式采用不同的编码表,每种编码表中将人类自然语言中不同的字符映射到不同的二进制代码,人类向计算机发送信息采用人类自然的语言,之后经过指定的编码方式编码成二进制代码交给计算机进行运算,计算机运算的结果----二进制代码,再经过这个编码方式解码成人类能够识别的字符串;这样完美的解决人和计算机的交互;
1 编码类型
<1> 字符编码类型
① 英文字符编码
| 编码方式 | 一个字符映射的二进制位 | 编码字符 | 特点 |
|---|---|---|---|
| ASCII | 1byte | 英文字符、标点符号、特殊符号 | 所有其他编码方式的子集 |
② 全球字符编码
| 编码方式 | 一个字符映射的二进制位 | 编码字符 | 特点 |
|---|---|---|---|
| unicode | ucs2---2byte,早期使用 ucs4---4byte,当前主流 |
全球所有的字符 | 兼容ASCII |
| utf-8 | 1byte:英文字符 2byte:欧洲字符 3byte:亚洲字符 | 全球所有的字符 | 兼容ASCII |
| utf-16 | 定长2byte编码全球所有的字符,英文字符同样2byte编码 | 全球所有的字符 | 不兼容ASCII |
| utf-32 | 定长4byte编码全球所有的字符,英文字符同样4byte编码 | 全球所有的字符 | 不兼容ASCII |
③ 中文字符编码
| 编码方式 | 一个字符映射的二进制位 | 编码字符 | 特点 |
|---|---|---|---|
| GB2312 | 英文:1byte 中文:2byte | 7k中文字符 + ASCII编码 | 兼容ASCII |
| GBK | 英文:1byte 中文:2byte;windows下名称为ANSI | 24k中文字符 + ASCII编码 | 兼容ASCII |
| GB10830 | 英文:1byte 中文:2byte | 70k中文字符 + ASCII编码 | 兼容ASCII |
④ 其他国家字符编码
| 编码字符归属地 | 编码方式 |
|---|---|
| 日文字符 | shift-jis |
| 韩文字符 | windows949 euc-kr |
| 泰语字符 | tis-620 |
| 等等。。。。 |
<2> 非字符类型编码方式
| 编码文件类型 | 编码方式 |
|---|---|
| 图片文件类型 | 预测编码、变换域编码等; |
| 音频文件类型 | PCM、WAV、MP3、OGG、MPC、WMA等 |
| 视频文件类型 | H.26x系列,MPEG系列,AVS,RMVB等; |
<3> 编码方式的总结
常见的编码方式均为字符类型的编码,此种类型的编码仅仅能够将某种语言中的字符编码程对应的二进制码,而不能编码图像、音频、视频类型的文件;程序开发人员一般对于图像、音频、视频类型的数据,是直接采用二进制码进行操作,只有专业人员才需要采用特定的编码方式;
2 各种编码方式详解
<1> ASCII编码
特点: 仅仅解决英文字符的编码,有效编码对应的十进制数为:0-127; 128-255用于扩展;
计算机最早是由美国发明的,ASCII编码是最早的编码方式,其主要是用于解决英文字符、符号、特殊字符与二进制的映射关系;此后由于计算机的发展,产生了针对不同国家的字符的字符编码方式和万国码;其他所有的编码方式都是在ASCII编码的基础上发展而来,即所有的其它编码方式中都包含了ASCII码表,无论某种字符编码方式中采用多少位去编码一个字符,所有的编码方式中针对英文字符、符号、特殊字符的二进制码和ASCII编码表中的二进制码完全相同;
<2> Unicode
① unicode分为两种类型:ucs2、ucs4; 早期采用ucs2去编码全球所有的字符,随着计算机的发展ucs2并不能完全的映射全球所有的字符,故此目前主流的Unicode编码方式都是采用ucs4这种类型,即采用4byte去编码全球所有的字符;
查看unicode类型的方法:
import sys
print(sys.maxunicode)
输出:
65535 : 采用ucs2
1114111 : 采用ucs4
② Unicode编码方式对比其他的编码方式需要占用更多的二进制位,故此Unicode编码方式仅仅工作在内存中,一旦内存中的文件写入到磁盘或要通过网络进行传输时,是必须要转换为其它的编码方式;此规则已经成为计算机工作的一种标准;
③ 内存中的字符编码----Unicode编码,且Unicode编码方式仅仅只能也只应用在内存中;
内存中为何采用unicode编码的原因:
Unicode是万国码,能识别全球所有的字符,同时是定长的4byte的编码方式;而utf系列的编码方式不同的字符类型编码长度不一致,在内存中进行运算时,可能会产生问题;而Unicode的定长特点完美的避免了运算时的此种缺陷;同时由于内存中的运算计算量不会是全部的数据,故此采用Unicode编码同样不会对内存产生很大的影响;
此即为:内存中为什么采用Unicode编码进行运算的原因;
④ unicode编码方式能与其他任何的编码方式进行转换,而其他任意两种编码方式均无法直接完成转换;而必须采用unicode编码进行转换;其关系如下:

unicode占用的存储空间与其它编码的比较:
unicode针对除英文字符之外的所有类型的字符,都是采用4byte进行编码,故此同样的数据,采用unicode所需要的bytes比其他的编码方式要多的多,在进行存储和网络传输时要占用更多的存储空间和网络传输资源;故此unicode编码是不能用于进行存储和网络传输的;
文件大小的计算方式:
数据在计算机中是以字符串形式的存在的,字符串的组成结构体字符在计算机内部是以二进制01形式存在的,故此数据在计算机内部即是01构成二进制字符串;每个字符串采用不同的编码方式进行编码时,占用的二进制位不同,故此可以计算出,文件中的字符串个数,然后计算出文件所占用的bytes的个数,即计算出文件的大小;
为什么内存中采用的是unicode编码
1 unicode解决了全球所有的字符编码,故此gbk等国家区域范围的编码方式不能作为内存的编码方式;
2 unicode采用固定的4byte编码,在将数据加载到内存中时,直接根据4byte进行一次解码操作,解码操作效率更高,对比utf-8的不定长编码,在解码非ascii字符时需要多次尝试判定字符的类型,效率高的多;
<3> UTF系列编码
特点:
UTF-8: 可变长编码方式:英语字符--1byte 欧洲各国字符--2byte 亚洲各国字符--3byte;
UTF-16: 定长2byte编码全球常用的字符,英文字符同样2byte编码,故此其不兼容ASCII编码; windows下名称:Unicode
UTF-32: 定长4byte编码全球常用的字符,英文字符同样4byte编码,故此其不兼容ASCII编码;
<4> GB系列编码
中文字符共计9w多个,GB系列都是对中文字符的不完整编码,并不能编码所有的中文字符;
GBK: window下名称ANSI;
<5> 其他国家语言字符编码
所有的其他的字符编码方式中,均是由ASCII编码方式发展而来,包含ASCII编码作为其子集;
3 计算机底层涉及的编码
<1> 计算机对数据的处理总结
1 计算机是电气设备,其只能识别电平的高低对应的数字01,故此计算机只能识别二进制码;
2 编码解决了人类语言与计算机的相互识别的问题;
3 计算机底层---内存中所有的数据,均识别为unicode字符串;数据结构在内存中是不存在的,内存中只有字符串,数据结构的元数据会采专用字符进行转换,然后在程序中予以展示成特定的数据类型,如:列表、元祖等等;而在存储或网络传输上的字符串则是其它编码方式的字符串;
4 计算机处理的数据的来源--文件、网络;文件中的数据其实质都是一个字符串,只不过这些字符串内有一些格式控制字符,如\n \r \t使得文件的内容在输出时并不像是一个字符串;同理网络上的数据也是如此;故此,计算机底层数据的处理都是---字符串;
5 计算机处理的字符串,计算机底层处理的数据都是二进制字符串;在内存中,这些字符串是unicode字符串,即python3中的str类型,而在文件或网络传输中均为其它编码格式的二进制字符串,即python3中的bytes;在计算机底层的二进制字符串,在显示给用户看的时,均采用了对应的编码格式解码成人类能够识别的字符串,千万不要理解为人类所看到的字符串即计算机底层真实存在和处理的数据;
<2> 内存、存储、网络传输
| 位置 | 编码方式 | 字符串类型 |
|---|---|---|
| 内存 | unicode | unicode编码的字符串---即str |
| 存储 | unicode之外的任意编码方式 | 非unicode编码的字符串--即bytes |
| 网络传输 | unicode之外的任意编码方式 | 非unicode编码的字符串--即bytes |
<3> 文件操作与编码
① 打开文件
目标:将磁盘上文件的内容加载到内存中,然后用以完成对文件的进一步操作;
编码方式:
磁盘:非unicode编码
内存:unicode编码
必要条件:
打开文件即将文件的内容加载到内存中,必须要将文件解码成unicode,然后才能正常加载到内存中;打开文件一般会采用一些文件编辑工具,如:notepad++ txt open()等,而文件编辑工具都设定了默认的编码方式,这个默认的编码方式用于指定将磁盘上的文件加载到内存时的完成解码操作时所采用的编码方式,和将内存中的数据写磁盘时采用的编码方式;若打开文件时,这些文件工具的指定的编码方式,与文件内容的编码方式不同,则无法完成正常的解码操作;故此采用什么编码方式写的文件,一定要采用什么编码方式打开;同理,若是采用源代码进行打开文件操作,此时则必须要采显示的指定编码参数,说明打开文件时采用的编码方式;
② 读文件
读文件的前提是打开文件,打开文件的方式有:系统调用、程序工具,如:sublime txt open()等,这些程序运行在内存中,故此打开文件的操作也是发生在内存中的,文件也是被加载到内存中;文件磁盘或网络传输设备上加载到内存空间中,必须采用源文件的内容或传输的对应的编码方式解码成unicode字符串;完成打开后即解码完成后,此时人看到的数据的内容全部是内存中的内容,在计算机底层表现为内存中的unicode编码的二进制,而人看到的内容则是unicode解码后的人类可以识别的字符串;
③ 写文件
写文件的前提也是打开文件,此时人类读写的操作都是发生在内存中,故此读写的均为unicode字符串,在写入时,人类向文件中写入的字符均为unicode字符,在计算机底层会自动将人类写入的字符编码成unicode字符,同时显示给人类看的则是unicode解码的人类可以识别的unicode字符串;写入完成则采用打开文件的程序或函数的默认编码方式进行编码后,进行存储或进行网络传输;
<4> 输出与编码
计算机底层对数据的处理,都是二进制码;唯一的区别在于在内存中是Unicode编码的二进制字符串,而在网络和存储中则是非Unicode编码的二进制字符串;
打开文件、读写文件,都需要借助于文件操作程序,而这些程序都是在内存中运行的,故此文件的读写操作,都是在内存中进行,即文件的读写操作都是读写的内存中的字符串;而内存中都是采用的unicode编码;
计算机的输入、输出均是文件,只不过文件有一种特殊的文件类型---即标准输入、标准输出---终端,计算机只有将数据写入到这种终端文件中,然后打开终端文件人类才能看到输入输出的内容;
linux一切皆文件,此定律适用于所有的文件操作和输入输出;输入输出同样都是文件,输入可以认为是读文件,输出则是写文件;
人类看到输出的底层原理:---标准输出、看到的文件内容的底层原理
step1: 计算机产生输出
程序执行生成数据----内存中的二进制Unicode字符串,然后写入到输出文件中,此时计算机底层自动将Unicode编码的二进制编码程标准输出文件默认的编码方式编码的byte字符串;
step2: 打开输出文件,获取输出
打开输出文件,调用打开输出文件的工具的默认编码方式进行解码后,还原成二进制Unicode字符串,然后在系统底层自动完成Unicode的二进制字符串到人类能够识别的语言字符串的反向转换,呈现出人类能够识别的字符;即此时人类看到的内容;
case1: 文件的读写,均是发生在内存中,读写的内容在内存中表现为unicode str,而给人类看到的都是unicode解码后的人类能够识别的字符串;
case2: 存储和网络传输设备上的数据: 都是采用的其他的编码方式的二进制;无论是通过什么方式人类都无法直接查看到,而必须加载到内存中,进行查看;
程序执行的结果会产生输出,此输出的内容会从内存中发送到要输出的位置;而输出的位置对应了不同的输出设备;常见的输出的位置有:文件、标准输出、标准错误输出;
程序执行的结果的输出,其实质相当于将内存中的unicode字符串写入到指定的操作系统的某个文件中;同上,unicode字符串不能直接进行网络传输和存储,此时同样要进行编码,编码成对应的输出终端的编码格式进行存储和显示给用户看;如在cmd命令下获取到程序的输出,内存中的unicode字符串,要调用cmd工具的默认编码方式gbk进行输出,然后采用gbk解码给用户显示;
4 编码的几个问题的解释
① 采用什么编码写的文件,必须要采用什么编码方式打开文件
原因:
文件打开的过程,即是将存储或网络传输上的二进制加载到内存中,此时必须要将存储或网络设备上的非unicode编码的二进制转换为unicode编码的二进制;而这个过程中,计算机是无法识别存储或网络传输采用的是哪种编码方式,故此在将文件或网络传输中的数据加载到内存中时,必须要指定一种编码方式,此编码方式即使设定将存储或网络传输上的二进制码转换成Unicode码所采用的编码表;
指定编码方式时,由于除了unicode之外,任意的两种字符编码方式都不能互相识别,故此采用什么编码方式保存的文件或网络传输设备上的二进制,必须采用该编码方式完成解码,转换为unicode;否则一旦采用其他的编码方式,其是无法正确的识别文件或传输设备上的二进制,即会产生不能转换的问题,造成解码错误;
| 打开文件的类型 | 指定编码的方式 |
|---|---|
| 程序源代码 | 必须采用参数的方式指定编码方式 |
| 程序 | 采用程序默认的编码方式打开文件 |
② python2中文乱码,python3中文不乱码
| 版本 | 解释器的默认编码方式---把解释器看成一个文本编辑工具 | 内存编码方式 |
|---|---|---|
| python2 | ASCII | Unicode |
| python3 | utf-8 | unicode |
python程序的执行过程:
step1: 解释器将程序文件加载到内存中;
step2: 解释器解释执行程序;
原因:
无论是python2还是python3程序的执行,其程序的执行前提条件必须要将程序文件加载到内存中,即打开程序代码文件,故此此过程必须要将程序代码文件的非unicode字符串,转换为内存中的unicode字符串,此时即必须遵循程序文件采用什么编码方式写,则必须采用什么编码方式打开;
python2: 若程序代码采用其它任意编码方式写的,若程序代码中仅仅只含有英文字符,由于其他所有的编码方式都是兼容ASCII编码是ASCII编码的一个父编码集,故此其他编码方式编码的ASCII字符是同ASCII编码的ASCII字符完全相同的,故此python2的解释器通过ASCII编码方式能正常的将程序代码转换成unicode字符串,然后加载到内存中,进行执行的;若一旦程序代码中含有中文字符,那么python2的解释器采用ASCII编码是无法正确的解码中文字符,故此产生语法错误;
解决方法:---声明编码
# -*- coding:utf-8 -*-
#此行代码的含义,即让解释器采用指定的编码方式去完成程序文件打开时的编码转换,将程序代码文件的程序代码,采用指定的编码方式解码成unicode字符串;
python3: 若程序代码采用其它任意编码方式写的,若写入的代码中仅仅只含有英文字符,由于其他的编码方式中都是ASCII编码发展起来的一个父编码集,故此其他编码方式编码的ASCII字符是同UTF-8编码的ASCII字符完全相同的,故此python3的解释器通过UTF-8编码方式能正确的解码英文字符,然后加载到内存中进行执行;一旦程序代码中含有中文字符且代码采用UTF-8进行编码的,那么python3的解释器采用UTF-8编码也是能够解码中文字符加载到内存中的,然后执行程序的;若程序代码是采用GBK系列的编码方式进行编码的,而python3采用utf-8进行,同样是无法正确的完成解码操作,产生解码错误;
总结说明:
python程序的执行,首先第一步必须要将程序文件加载到内存中,然后进行执行;加载到内存中必须要将程序文件完成解码,解码成unicode字符串;若程序代码中仅仅只有ASCII字符,则无论程序文件是什么编码方式写的,由于所有的编码方式编码的ASCII字符对应的二进制都是相同的,故此python2 python3都能正常完成解码成unicode字符然后执行; 而一旦程序代码中含有非ASCII字符,如中文,则python2的ASCII编码必定无法完整转码操作,必定产生语法错误;而python3的调用的UTF-8编码方式若能编码这些非ASCII字符,则能正常执行,若python3的utf-8编码方式不能编码这些非ASCII字符,则同样的utf-8也会产生解码错误;
案列:
程序文件采用gbk编码写的代码,且其中含有非ascii字符;
则python2 python3都会产生解码报错;
③ python2 python3的区别
区别一:编码方式不同
Python2: 默认编码方式为ASCII---打开文件,保存文件的编码方式
python3: 默认编码方式为unicode--打开文件,保存文件的编码方式
解决方式:---编码声明行
#-*- coding:utf-8 -*-
区别二:输出编码不同
python2: 内存输出采用的解释器定义的编码方式进行编码后输出
python3: 内存输出输出的是原生的unicode字符串
案例:程序代码如下
# -*- coding:utf-8 -*-
print('中国')
执行结果:
python2在cmd命令下执行,输出乱码,而python3正常输出;
解释:
python2: 正常执行,但是python2执行后的输出---内存中的‘中国’Unicode二进制会转换成python2解释器的编码方式的二进制,此案例转换成utf-8的二进制码;然后进行输出;在cmd命令行进行输出,相当于cmd为一个文本工具打开python2执行结果的输出文件,此时系统会采用cmd命令行的默认编码方式--gbk去解码utf-8的二进制码,故此乱码;
python3: 正常执行,但是python3执行的输出---输出的是原生的Unicode字符串,此时cmd采用gbk去打开unicode的二进制是能正常完成解码操作,故此正常显示;
解决方式:字符串标记符u
u'字符串'
程序代码为:
# -*- coding:utf-8 -*-
print(u'中国')
④ 字符串标记符
u:指定字符串为原生unicode字符串进行处理或输出;Python3默认的字符串类型;
r: 字符串中的特殊字符,不做转义解释,而是原样传递给解释器执行;
b: bytes对象的标识符,bytes字符串能直接进行存储和网络传输;
5 编码后的bytes类型和字节码
① 字节码和bytes
字节码:
字节码是解释性编程语言为了提高解释性编程语言的执行效率而引入的一种中间代码,解释器本身是一种二进制可执行程序,字节码是能够被这种解释其二进制程序能够识别的代码,其是非二进制的,在运行时必须通过解释器再次解释---编译成真正的二进制才能执行;
bytes:
bytes是真正能够被cpu所识别的二进制,存储和网络传输的对象即使此种数据类型;
总结:
字节码和bytes没有任何关联
6 字符串类型
| 字符串类型 | 实质 | 存在位置 | 计算机底层表现形式 | 输出形式 |
|---|---|---|---|---|
| str | Unicode字符串 | 内存 | unicode编码的二进制 | unicode解码后的人可识别的字符串 |
| bytes | 非Unicode字符串 | 存储设备和网络传输 | 非unicode编码的二进制 | 英文字符:b标识的ASCII字符 中文字符:b标识的十六机制显示 |
扩展说明:
为什么ASCII字符的bytes类型人看到的是ASCII字符,而中文字符则是十六机制字符;
原因:
人看到的内容,或是说计算机将底层二进制输出给人看的时候,均是经过解码操作了的;
ASCII字符: ASCII编码表是其他所有编码方式的一个子集,即ASCII字符的二进制在所有的编码方式中其二进制都是完全相同的;故此针对ASCII字符,所有的编码方式编码后的ASCII字符其二进制完全相同;str对象时Unicode编码的二进制,而bytes对象则是非Unicode编码的能够直接进行存储和网络传输的二进制;由于无论采用什么编码方式,ASCII字符的二进制都相同,故此显示bytes对象中的ASCII字符时采用的是人类能够识别的ASCII字符,而并不是二进制形式;
中文字符: 针对中文字符,不同的编码方式编码后的二进制是完全不同的,bytes是编码unicode之后形成的二进制,输出给人看时,同样是可以直接解码还原成中文字符的;但是不同的编码方式所编码后形成的二进制是不同的;故此同一个unicode字符若采用不同的编码方式,其对应的二进制是不一样的,若还原成中文字符,人根本无法区分,底层计算机上真正要传输和存储的底层二进制数据是什么样的; 而对于ASCII字符,无论什么编码方式产生的bytes,其底层真正要存储和传输的二进制是完全相同的;故此中文字符是直接采用其编码后的二进制转换后的十六进制形式进行输出的,之所以采用16进制的原因是避免直接采用二进制输出时输出的内容过长,这样便于让人类认识到,真正进行存储和网络传输的内容;
总结:
bytes对象的底层二进制,对于ASCII字符而言,会进行解码后输出;
bytes对象的底层二进制,对于非ASCII字符,会直接输出其二进制转换为十六机制后结果;
str与bytes之间的关系
| 类型 | 操作 | 类型 |
|---|---|---|
| str | encode() | bytes |
| bytes | decode() | str |
7 python程序执行与编码
step1: 采用编辑器编写程序源代码
采用文本工具编写程序源代码,然后保存源代码文件;注意有些文本编辑工具,如:typora、pycharm等文本编辑工具时,其会自动周期性的保存文件;此时保存文件时,写入到内存文件中的程序源代码会调用编辑器的默认编码方式,编码之后存储在磁盘或其他存储系统上;
step2: 运行解释器程序,打开源代码程序文件
启动解释器程序,解释器进程会去磁盘上将源代码文件加载到内存中;此过程中解释器可以看成为一个文本编辑工具,此时需要打开源代码程序文件; 解释器会采用其默认的编码方式去解码程序文件中的字符串;---此过程中:python2默认采用ASCII编码,而python3默认采用UTF-8编码方式去解码源代码程序文件;
此时,若解释器的默认编码方式不能完成源代码程序文件的编码方式到Unicode的转换,则会导致编码错误;
step3: 解释器打开文件之后,读取源代码程序文件的内容,开始执行源代码,产生输出;
解释器运行在内存中,此时程序生成的数据必然是存在于内存中的Unicode字符串;而一旦采用程序指令,指定输出指定的字符串到某个位置时,即相当于将指定的内存中的Unicode字符串,写入到指定的普通文件或终端文件上;
在输出时---写文件或标准输出; python3输出的是内存中原生的Unicode字符串;而python2输出的并非是内存中的Unicode字符串,而是先将内存中的Unicode字符串,采用Python2解释器指定的编码方式进行编码后的字符串;此后调用普通文件或终端文件的默认编码方式,编码python3或python2输出的字符串后完成存储; 此即为一旦程序代码有中文字符,即使python2中声明了采用utf-8编码,在cmd命令行下执行程序代码,仍然出现乱码情况,而python3仍然正常显示的原因;
step4: 执行的输出,被计算机予以显示
假如:在cmd命令行下执行python程序,输出中国;
python3: python3输出中国的Unicode原生字符串,被操作系统调用终端文件的默认编码方式完成编码后存储---操作系统的默认编码方式,windows默认采用gbk,linux默认采用utf-8;cmd命令则打开该文件,由于cmd本身即为终端,故此cmd能正常将编码好的非Unicode字符串还原成Unicode字符串,然后解码程人类可以识别的字符显示给人类;
python2: python2若采用默认的编码ASCII编码,则根本无法解码程序代码中的中国,故此根本无法正常的打开文件,程序无法执行;若python2采用utf-8编码,则程序能够正常执行,此时产生输出时,python2现将内存中的元素Unicode字符,先转换成utf-8编码的字符串然后输出,然后调用系统默认的终端文件的编码方式编码或解码完成存储和显示;
step5: 程序执行完成
总结:
普通文件,若采用源代码打开,必须指定编码参数;而采用文本编辑工具或终端文件由于其都设定了默认的编码参数,不在需要手动的去指定;
8 python2 python3字符串的区别
<1> Python2的字符串
| 类别 | 应用 | 特性 | 字符串标记 |
|---|---|---|---|
| str | python2程序代码中的字符串均为此种类型 | 带有编码属性 | 无 |
| unicode | str经过decode()操作后的字符串 | 内存中的Unicode字符串 | u |
总结:
1 python2中的字符串类型:str unicode均是basestring这个类的子类;
2 python2程序中定义的任何不带字符串标记符号的字符串均为str类型,其带有编码属性,在被python2解释器处理和输出时要预先decode()然后加载到内存中,在经过encode()操作之后产生输出,输出到文件时还会调用文件的编码方式再次进行编码;
<2> python3的字符串
| 类别 | 特点 | 特性 | 字符串标记 |
|---|---|---|---|
| str | python3程序代码中的字符串均为此种类型 | 原生Unicode字符串 | 无/等同于u标记 |
| bytes | str经过encode()之后能够存储和传输的字符串类型 | 带有编码属性 | b |
| bytearray | 可变的bytes | 带有编码属性 | 基本不用 |
总结:
1 python3程序中定义的字符串,均为原生Unicode字符串;
2 python3程序中定义的字符串,能够直接被python3解释器所处理和输出,即python3解释器处理和输出的都是程序代码中定义的Unicode原生的字符串--str;只有要经过存储和网络传输时才会再次经过编码操作;
9总结
计算机只能识别为二进制代码,故此计算机底层仅仅只有一种数据类型---字符串类型,且为二进制字符串;故此:
1> 应用程序的数据类型,如python3中的list数据结构[],都是采用编码表将其数据结构标识符如[] 以及元数据信息经过编码成二进制保存,存储数据和网络传输时,真实的数据和数据结构的二进制信息一起传输,然后在输出时,才解码展示出来;
2> 计算机底层将数据全部处理为二进制字符串,故此在计算机的所有的硬件设备上的数据全部是二进制字符串,这些二进制字符串在内存中表现为unicode字符串,在存储设备和网络传输上变现为其它编码方式的二进制字符串;而只有在输入输出时,才会将unicode字符串采用对应的编码方式解码成人类能够识别的字符串;在python中,字符串表现形式有str和bytes对象两种;
3> 计算机内部仅仅只有一种数据类型:字符串; 而在进行存储和网络传输时,才会将unicode字符串采用其他的编码方式转换为其它编码方式的二进制bytes对象; 只有在输出:无论是文本工具打开、终端输出时才会将二进制bytes对象采用对应的编码方式decode后加载到内存中,然后解码unicode字符串成人类可以识别的字符串; 总结一点:计算机内部只有二进制,在内存中为unicode字符串,而在存储设备和网络传输上为其它编码方式的bytes对象;而在输出显示是才将二进制解码成人类可以识别的字符串;
4> 编码: 即是将人类能够识别的字符采用对应的编码方式映射为二进制码,或将内存中Unicode字符串采用指定的编码方式编码程某种特定的bytes对象;
5> 解码: 即将二进制码还原成人类能够识别的字符,或将bytes对象转换成unicode的字符串;
6> 文件操作中,采用open()打开文件时,若采用了文本方式打开,其需要指定编码方式,在wirte方法写入字符串时,会采用open()中指定的编码方式,将字符串转换为对应的二进制bytes后再进行存储;
10 补充和扩展
① cmd命令行修改编码方式的方法
显示编码方式:
chcp //显示当前的编码方式---默认输出936----标识采用gbk编码
修改编码的方法:
chcp 编码标识数字 //如: chcp 65001 即修改cmd命令行的编码方式为utf-8
常用的编码标识数字:
437 --ASCII
936 --GBK
65001 --utf-8
② 字符串标记符号
| 标记符号 | 功能 |
|---|---|
| u | u标识其后跟的字符串以unicode格式存储,python解释器会根据其默认的编码方式或编码声明行定义的编码识别u后的字符串此后该字符串的所有的处理均是采用unicode原生字符串的方式进行处理;---此标记仅仅对Python2有用; python3: 所有的字符串默认就带有u标记,即全部当成原生Unicode字符串进行处理; python2: 默认字符串str带有编码属性,在进行处理时并非处理的为原生的Unicode字符串,而是带有编码属性的字符串,带有的编码属性为python2的解释器的编码方式,故此在输出时常常因为str带有的编码属性与输出终端的编码方式不一致产生乱码的现象; |
| b | 标识字符串为bytes类型的字符串; |
| r | 默认情况: 字符串中的有特殊含义的字符,如转移字符等会先经过特殊的处理后交给解释器进行解释执行; r标记的字符串: 字符串中的所有的字符,无论是否包含有特殊含义的字符均不作特殊处理原样交给解释器处理 |

浙公网安备 33010602011771号