Python 的环境我们已经搭建好了, 可以开始学习基础知识了. 但是, 在此之前, 还要先说说编译器与解释器相关的内容.
如果这部分内容, 让你觉得难以理解或不能完全明白, 可以暂时跳过, 等以后再回过头来重新读一遍.
一, 数据的表示方式
我们都知道, 现实生活中, 数字的表示方式有很多种, 常见的有二进制, 八进制, 十进制和十六进制. 十进制我们都很熟悉, 加法口诀表我们都背过, 主要是使用 0~9, 这 10 个阿拉伯数字来构建整个十进制的体系, 其中最核心的法则是 "逢十进一", 借位则是 "借一当十". 那么为什么全世界不管什么国家, 什么历史, 什么文化水平基本都是用十进制作为基本进制呢? 是因为我们人有 10 个手指头, 掰起来最方便! 我们对十进制有着天然的友好度.
那么对于计算机呢? 计算机不是人, 没有 10 个手指头可以掰, 所以它用不了十进制. 那么它用几进制? 二进制! 二进制是用 0 和 1 两个数码来表示的数, 也就是形如 010101010 的样子. 它的基数为 2, 进位规则是 "逢二进一", 借位规则是 "借一当二".
为什么计算机要使用二进制作为自己的机器语言也就是数据的表示方式呢? 因为计算机最小的计算单元是根据开关状态高低电平来确定的, 它只有开和关, 高和低的概念, 换成数学就是 0 和 1 的两种. 同样的, 在物理存储方面, 硬盘的磁道只能区分打孔和未打孔的状态, 也是 0 和 1 两种. 同时二进制便于进行加, 减运算和计数编码. 二进制与十进制数易于互相转换. 二进制便于逻辑判断 (是或非), 逻辑判断通常也是两种状态, 这和二进制很搭配. 二进制表示数据还具有抗干扰能力强, 可靠性高的特点, 因为当受到一定程度的电磁干扰时, 只要可以分辨出它是高电平还是低电平, 至于高多少或低多少并不重要, 就能区分 0 和 1, 这在网络信号中, 就是天生自带抗干扰能力.
但是, 在人机交流上, 二进位制有致命的弱点, 数字的书写特别冗长, 并且没有人类可读性! 例如, 十进位制的 100000 写成二进制就是 11000011010100000, 长了好几倍, 而且你能从一个这么长的二进制数里读出它的十进制数是多少吗?
计算机不能独立存在, 目前也无法自我创造, 不管是输入还是输出, 它的一切都必须和人交流. 那么问题来了, 人类只能读 10 进制和英语, 汉语等, 可计算机只会 010101, 至于英语, 汉语对它而言更是天书. 那么我们是怎么和计算机交流的呢? 怎么将我们的英语或者汉语编码成计算机能够识别的 1010101 呢?
二, 编程语言发展历程
1. 打孔纸条
我们已经知道了计算机只懂机器语言, 也就是二进制的数据表示方式, 任何对它的操作和编码, 最终都要统一到这上面来, 然而这是一个悲伤的故事.
起初, 为了让计算机按我们的想法工作, 程序员不得不编写计算机可以读懂看明白直接执行的机器码, 也就是 01010101 的样子, 打孔字条就是这么干的. 用打没打孔来代表 0 和 1.OK, 计算机没问题, 它能无障碍阅读, 可程序员就难受了. 拍脑袋也能想得到这里面的问题. 容易出错, 效率低, 编写困难, 维护困难. 可能就是个简单的打印 "hello world", 也许就需要好几米长的字条. 这简直就是原始社会, 生产效率低下的令人发指. 发生个火灾什么的, 直接 Over. 唯一的好处就是无需转换, 可直接执行, 但相对缺点来讲, 这点好处完全可以被忽略.
2. 汇编语言
汇编语言是一种可编程器件的低级语言, 亦称为符号语言. 在汇编语言中, 用助记符代替机器指令的操作码, 用地址符号或标号代替指令或操作数的地址. 在不同的设备中, 汇编语言对应着不同的机器语言指令集, 通过汇编过程转换成机器指令. 也就是说不同平台之间不可直接移植, 它是平台相关的, 你在这个硬件平台写的汇编程序, 换到另外一套硬件上去是运行不了的. 因此, 汇编语言通常被应用在底层, 硬件操作和高要求的程序优化的场合. 驱动程序, 嵌入式操作系统和实时运行程序较多使用汇编语言. 相比于机器码, 它更偏向人类的语言习惯, 更易于编写和阅读, 也就是有一点抽象符号概念化了, 这大大提高了编程效率. 但是, 这依然是一种低级语言, 还有改善和提高的空间.
上面一段看得晕没关系, 简单地说就是汇编语言相比打孔纸条, 对人类更友好一点了, 至少能用几个类似 ADD\CALL\MOV 的英文缩写了. 但是, 它牺牲了一定的性能, 并且依然不够友好.
3. C 语言
在 C 语言之前其实还有很多低级语言, 我们不关心它们. 为了让编程更简单, 更高效, 聪明的计算机程序员, 一步步发明了 FORTRAN,BASIC,B 等许多语言, 然后在 1972 年诞生了无人不知, 应用最广, 影响最深, 至今仍然地位不可动摇的 C 语言.
C 语言为什么这么厉害? 归根结底是一句话: 直接操作硬件! 同样的算法, 用 C 语言, 其执行效率超过 JAVA 等语言很多. 那可能有人会问, C 和汇编和机器码比呢? 肯定是 C 慢, 但是写个汇编程序和写个 C 程序的效率差别那就更大了. C 语言在人类友好性和底层相关性上达到了一个高度的平衡. 这两者是互相矛盾的, 不可同时兼得.
C 干了些什么? 其实它就是在人类友好性方面相比以前跨出了更大一步. 人类是方便了, 可机器就迷糊了! 你给我这么多字符都是啥意思? 机器它只懂二进制啊! 那么 C 的代码是如何被执行的呢? 这就得请出编译器了!
编译器将编程语言写的代码翻译成机器能够执行或者说 "看懂" 的二进制机器码.
其实我们安装 JAVA 也好, C 也好, Python 也罢, 主要就是安装的这个编程语言的 "编译器".
4. Python 语言
在几十年前, C 语言是当之无愧的高级语言代表, 现在也依然是语言排行榜第二的霸主. 然而, 在很多领域, 它已经不太适用了, 现今更主流的语言是那些上手快, 简单易懂, 说白了就是门槛低的语言, 让更多的人能进入程序员行业, 让编程能更容易, 更快是未来的发展趋势. 也就是说, 需要进一步让编程语言更贴近人类语言, 更远离机器语言.
Python 就是这么一种语言. 它的语法简单明了, 更贴近人类的使用习惯. 作为一种动态解释性语言, 让人们在写代码的时候可以更多的关注业务逻辑细节, 而不需要花太多精力去关注数据类型定义, 程序运行效率等!
既然都说的是机器不懂的 "人话", 那必然也需要一个 Python"编译器". 对于 Python 语言, 广义上的 "编译器", 叫做解释器.
三, 编译器与解释器
编译器 / 解释器: 高级语言与机器之间的翻译官
都是将代码翻译成机器可以执行的二进制机器码, 只不过在运行原理和翻译过程有不同而已.
那么两者有什么区别呢?
用一个通俗的例子进行比喻: 我们去饭馆吃饭, 点了八菜一汤. 编译器的方式就是厨师把所有的菜给你全做好了, 一起给你端上来, 至于你在哪吃, 怎么吃, 随便. 解释器的方式就是厨师做好一个菜给你上一个菜, 你就吃这个菜, 而且必须在饭店里吃.
至于更深入的编译器和解释器是如何工作的, 请参考史诗巨著《编译原理》, 这本书有个外号, 叫做 "龙书".
四, Python 解释器种类
Python 有好几种版本的解释器:
CPython: 官方版本的解释器. 这个解释器是用 C 语言开发的, 所以叫 CPython.CPython 是使用最广的 Python 解释器. 我们通常说的, 下载的, 讨论的, 使用的都是这个解释器.
Ipython: 基于 CPython 之上的一个交互式解释器, 在交互方式上有所增强, 执行 Python 代码的功能和 CPython 是完全一样的. CPython 用 >>> 作为提示符, 而 IPython 用 In [序号]: 作为提示符.
PyPy: 一个追求执行速度的 Python 解释器. 采用 JIT 技术, 对 Python 代码进行动态编译 (注意, 不是解释), 可以显著提高 Python 代码的执行速度. 绝大部分 CPython 代码都可以在 PyPy 下运行, 但还是有一些不同的, 这就导致相同的 Python 代码在两种解释器下执行可能会有不同的结果.
Jython: 运行在 Java 平台上的 Python 解释器, 可以直接把 Python 代码编译成 Java 字节码执行.
IronPython: 和 Jython 类似, 只不过 IronPython 是运行在微软. Net 平台上的 Python 解释器, 可以直接把 Python 代码编译成. Net 的字节码.
五, Python 的运行机制
Python 作为动态解释性语言, 其运行机制可参考下图 (图片来自网络, 其中的 "编译器" 是对解释器的广义称呼):
都说解释器慢, Python 也有想办法提高一下运行速度的, 那就是使用 pyc 文件. 这点参考了 JAVA 的字节码做法, 但并不完全类同.
我们编写的代码一般都会保存在以. py 为后缀的文件中. 在执行程序时, 解释器逐行读取源代码并逐行解释运行. 每执行一次, 就重复一次这个过程, 这其中耗费了大量的重复性的解释工作. 为了减少这一重复性的解释工作, Python 引入了 pyc 文件, pyc 文件是将 py 文件的解释结果保存下来的文件, 这样, 下次再运行的时候就不用再解释了, 直接使用 pyc 文件就可以了, 这无疑大大提高了程序运行速度.
对于 pyc 文件, 你必须知道以下几点:
对于当前调用的主程序不会生成 pyc 文件;
以 import xxx 或 from xxx import xxx 等方式导入主程序的模块才会生成 pyc 文件;
每次使用 pyc 文件时, 都会根据 pyc 文件的创建时间和源模块进行对比, 如果源模块有修改, 则重新创建 pyc 文件, 并覆盖先前的 pyc 文件, 如果没有修改, 直接使用 pyc 文件代替模块;
pyc 文件统一保存在模块所在目录的__pycache__文件夹内.
如下图所示, modula_a 被 module_main 导入后会生成对应的 pyc 文件, 但是 module_main 不会生成 pyc 文件!!
来源: https://www.cnblogs.com/jqc6/p/11610435.html