解释型语言和编译型语言的不同以及Python如何运行

计划写关于Python中如何实现属性管理、函数(或类方法)管理、类管理的几篇成系列的文章。

而这篇文章写在这个系列之前,希望对后面几篇文章的理解有所帮助。

老实说,我也是在网上搜索了一些资料才写的这篇文章,如果有的地方写的不够好,请指正...

何为编译?

生成目标文件。

且目标文件是针对特定的 CPU 体系的(注意,开头用了"且"字)。

为ARM生成的目标文件,不能被用于MIPS的CPU,也不能用于x86的CPU。反过来说也是成立的。

也就是说这段代码在生成目标文件的过错中就已经被翻译成了目标CPU指令,所以如果这个程序需要在另外一种CPU上面运行,这个代码就必须重新翻译。

而上述这个翻译过程叫做编译。

何为解释?

对于各种非编译型语言(例如python/java)来说,可能不存在某种翻译成中间文件的过错,可能存在某种编译成中间文件的过程

如果存在翻译过错,那么他们翻译生成的通常是一种『平台无关』的中间代码,这种代码一般不是针对特定的CPU平台,他们是在运行过程中才被翻译成目标CPU指令的,因而在ARM CPU上能执行,换到MIPS也能执行,换到x86也能执行,不需要重新对源代码进行翻译。

而由于这些中间代码并不是能在CPU上直接运行,所以需要某种中介(叫做虚拟机)在执行时负责把代码翻译成CPU能执行的指令。

区别

编译型语言生成的文件已经针对某个特定的CPU生成了最终文件,所以在下载的时候针对不同的CPU下载不同的文件,这就是为什么在网上下载某个文件时,Windows系统用户下载Windows的下载包(因为Windows是操作x86系列CPU的),而Android手机(因为Android是操作ARM系列CPU的)需要下载Android类型的下载包。

针对解释型语言,因为你的中间文件并不是针对某个CPU的,所以如果某人在网上共享了一个Python源代码或者中间代码(字节码),那么不管你运行什么操作系统,下载的文件是一样的。而如果你原来没有下载虚拟机的话,可能你需要下载一个虚拟机才能够运行这个下载的文件。

你可能会说,我只要装了Python,就可以运行下载下来的Python文件了呀,这是因为你下载的Python运行包中已经包含了一个虚拟机。

简单总结:

1,编译型语言在编译过程中生成目标平台的指令,解释型语言在运行过程中才生成目标平台的指令。

2,虚拟机的任务是在运行过程中将中间代码翻译成目标平台的指令。

优缺点

解释语言需要考虑不同平台的共性。比如A平台支持加法和乘法,而B平台仅支持加法。为了执行9乘9这个操作同时还要保证它在A和B两个平台上都能运行,必须将9乘9翻译成A.B两平台都支持的加法,即9个9相加。所以势必会影响效率。

解释语言具有跨平台的优点,只要在平台上装了针对于该平台的虚拟机,那么一次编写,N次运行,所以生产效率高。

当代码发生更改时,解释语言由于时解释一句执行一句,效率不会发生更改。但是编译语言需要重新编译,效率会受到影响。

对解释型语言来说,代码的错误检查发生在执行时。

Python的运作模式

讲了这么多,下面的部分是才是真正对我们编写代码有实际影响的。

python运行时分为下面的四步:

词法分析

句法分析

编译

解释

词法分析的工作就是将输入的原始代码分解为一些符号token(包括标示符,关键字,数字, 操作符等)。这个过程中是不会报任何错的。

句法分析程序再接收这些符号,并用一种结构来展现它们之间的关系(在这种情况下使用的抽象语法树)。此时如果出现句法错误,会有提示。

我们常说,Python运行时不会执行函数,所以也不会报函数中的错误。

其实是说的片面的,请看下面的代码,我在函数f中写了一個语法错误,Python会报错。

L=[1,2,3]

def f():

L1=[for i in L]

执行结果如下:

File "hh.py", line 4

L1=[for i in L]

^

SyntaxError: invalid syntax

在句法分析后Python接收这棵抽象语法树,并将它转化为一个(或多个)代码对象。此时会出现我们说的中间码,或者说字节码。

>>> def f(x=1,y=2):

... a='a'

... b='b'

... return x+y

...

>>> f.__code__

", line 1>

>>> dir(f.__code__)

['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_kwonlyargcount', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']

>>> f.__code__.co_name

'f'

>>> f.__code__.co_nlocals #定义的局部变量个数

4

>>> f.__code__.co_varnames

('x', 'y', 'a', 'b')

>>> f.__code__.co_argcount

2

>>> f.__code__.co_code #字节码

b'd\x01\x00}\x02\x00d\x02\x00}\x03\x00|\x00\x00|\x01\x00\x17S'

如果我们直接运行一个Python文件,那么Python在执行完后就把这个字节码文件删除掉了,因为Python认为复用性不高。

但是如果是一个模块文件,那么Python会存起来,我们来做个实验。

a.py

import b

b.py

def f(a=1):

print(a)

当我们运行只有唯一一条语句的a.py时,Python会创立一个__pycache__的文件夹,其中就包括了b.cpython-34.pyc文件,这个就是b.py的字节码文件,如果用open函数打开来看看,就会看到下面的二进制文件,如果用普通方式打开,那么会提示编码错误。

>>> open('__pycache__/b.cpython-34.pyc','rb').read()

b'\xee\x0c\r\n0%\xd8U\x19\x00\x00\x00\xe3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00@\x00\x00\x00s\x13\x00\x00\x00d\x00\x00d\x01\x00d\x02\x00\x84\x01\x00Z\x00\x00d\x03\x00S)\x04\xe9\x01\x00\x00\x00c\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\x0e\x00\x00\x00t\x00\x00|\x00\x00\x83\x01\x00\x01d\x00\x00S)\x01N)\x01\xda\x05print)\x01\xda\x01a\xa9\x00r\x04\x00\x00\x00\xfa\x13/home/aaa/proj/b.py\xda\x01f\x01\x00\x00\x00s\x02\x00\x00\x00\x00\x01r\x06\x00\x00\x00N)\x01r\x06\x00\x00\x00r\x04\x00\x00\x00r\x04\x00\x00\x00r\x04\x00\x00\x00r\x05\x00\x00\x00\xda\x08\x01\x00\x00\x00s\x00\x00\x00\x00'

解释器逐个接收这些代码对象,并执行它们所代表的代码。

题外话

以下题外话摘录于网上,如果有什么地方不对,请指正。

现在关于解释和编译的界限也不是特别清晰了。

Java需要预先把代码编译成虚拟机指令的,然后在运行这些虚拟机指令,有的教科书上会成为混合型或者半编译型。

像Python和lua这样就更不好分了,可以直接解释源代码运行,也可以编译为虚拟机指令然后再运行。

php编译之后的结果可以被Web Server缓存起来,甚至还可以先被翻译为C++,然后再编译。

.NET 的CLR运行时是Windows的组成部分,编译好的.NET 系列语言的代码直接生成可执行文件,然后被“直接”执行,看起来跟C没有什么太大的差别。

JavaScript可以被V8引擎编译为机器码然后执行,如果在node.js下,这个编译结果被缓存起来了,你说这跟编译好再执行的C有什么区别?

编译型语言

1、编辑:用编辑软件(EDIT.EXE或记事本)形成源程序(.ASM),如:LX.ASM;

2、汇编:用汇编程序(MASM.EXE)对源程序进行汇编,形成目标文件(.OBJ),格式如下:MASM LX.ASM;

3、连接:用连接程序(LINK.EXE)对目标程序进行连接,形成可执行文件(.EXE),格式如下:LINK LX.OBJ;

4、执行:如果结果在屏幕在显示,则直接执行可执行文件。

5、调试:用调试程序(DEBUG.EXE)对可执行文件进行调试,格式如下:DEBUG LX.EXE

目标代码由机器指令组成,一般不能独立运行,因为源程序中可能使用了某些汇编程序不能解释引用的库函数,而库函数代码又不在源程序中,此时还需要链接程序完成外部引用和目标模块调用的链接任务,最后输出可执行代码

1楼daodaoliang哦。博主内容写的不错,但是有好多错别字,看发音应该是你手误,我这里就提醒一下,内容写的很不错,学习了。

python无需编译解释执行,解释型语言和编译型语言的不同以及Python怎么运行相关推荐

  1. python语言是解释执行的、因此执行速度比编译型语言慢_解释型语言的特点与理解...

    解释型语言是什么?对比编译型语言有什么区别? 为了将高级语言转换成计算机能识别的机器语言,需要一个'翻译'过程.即编译或者解释 编译型语言 编译型语言的程序只要经过编译器编译之后, 每次运行程序都可以 ...

  2. python是一种编译语言_解释型语言和编译型语言的不同以及Python如何运行

    计划写关于Python中如何实现属性管理.函数(或类方法)管理.类管理的几篇成系列的文章. 而这篇文章写在这个系列之前,希望对后面几篇文章的理解有所帮助. 老实说,我也是在网上搜索了一些资料才写的这篇 ...

  3. java 编译 解释执行_关于Java的编译执行与解释执行

    编程语言分为低级语言和高级语言,机器语言.汇编语言是低级语言,C.C++.java.python等是高级语言. 机器语言是最底层的语言,能够直接执行.而我们编写的源代码是人类语言, 计算机只能识别某些 ...

  4. js 预编译 解释执行 作用域链 闭包

    <script>var a,b = 1;function c(x){var aa = 2;function d(){var ab = 3;}}var d = function(){//.. ...

  5. python 线程中出现执行错乱_多处理会导致Python崩溃,并在调用fork()时在另一个线程中出现错误...

    我对Python还比较陌生,并尝试为for循环实现一个多处理模块. 我有一个图像url数组存储在img_url中,我需要下载并应用一些Google vision.if __name__ == '__m ...

  6. python协程等待执行完成_当循环运行时,如何运行协同程序并等待同步函数的结果?...

    同步等待异步协同程序 如果一个异步事件循环已经通过调用loop.run_forever运行,它将阻塞执行线程,直到loop.stop被调用[请参阅docs].因此,同步等待的唯一方法是在一个专用线程上 ...

  7. Python程序的执行过程 解释型语言和编译型语言

    转载地址:http://www.cnblogs.com/kym/archive/2012/05/14/2498728.html 1.C++和C都是属于编译型语言,本来的.c文件都是用高级语言编写的,计 ...

  8. python语言是编译型语言-解释型语言与编译型语言

    一 定义 解释型语言 源代码不是直接翻译成机器语言,而是先翻译成中间代码,再由解释器对中间代码进行解释运行.程序不需要编译,程序在运行时才翻译成机器语言,每执行一次都要翻译一次. 多次解释,多次执行. ...

  9. python是一种编译语言_Python是编译型语言还是解释型语言?

    最近被这个问题困扰良久,在网上看了很多博客,总结一下: 1. Python是一门解释型语言? 初学Python时,听到的关于Python的第一句话就是,Python是一门解释性语言,我就这样一直相信下 ...

  10. 理解python先编译后解释的特点

    理解python先编译后解释的特点 1. CPython默认的标准解释器编译器.JPython支持Java集成,可以生成Java字节码并在JVM中解释执行.IronPython支持.NET集成. 2. ...

最新文章

  1. 【Sql Server】DateBase-结构化查询基础
  2. oracle自动售票服务器,一种基于Oracle数据库客户端的业务自动处理方法与流程
  3. 自动化部署之gitlab备份和恢复
  4. Servlet 生命周期、工作原理
  5. inputstream转fileinputstream对象_FileInputStream类:文件字节输入流
  6. 读取bmp格式数据--实践思考
  7. C++ Primer 第五版 第6章 6.7——函数指针习题答案
  8. java选择排序算法实现
  9. JVM 字节码 对照表
  10. xss攻击突破转义_每个人都应该了解的7种xss漏洞
  11. C#中List〈string〉和string[]数组之间的相互转换
  12. jqgrid 横向滚动条
  13. 获取 app 签名的方式汇总
  14. xmind思维导图怎么把字体变大_XMind 使用指南 | 让思维导图放大你的影响力
  15. R:应用时间序列分析--基于R(1)第一章 时间序列分析简介
  16. 选择变色镜片——爱眼护眼
  17. 《仙剑奇侠传3》仙术合集
  18. win7系统笔记本架设无线热点(AP)
  19. 4.12 使用格式刷实现单元格样式的快速复制 [原创Excel教程]
  20. Kernel Trick

热门文章

  1. Git常用指令的使用
  2. 支持向量机(Support Vector Machine,SVM)—— 线性SVM
  3. Java的split()用法
  4. GloVe损失函数的理解
  5. 绝对路径与相对路径cd命令的使用
  6. mysql-proxy读写分离,负载均衡
  7. 《实时控制软件设计》团队项目第三天工作日志
  8. 程序状态字寄存器PSW
  9. 上周热点回顾(6.4-6.10)
  10. Recursive implementation of the Gaussian filter[翻译]