解释型 vs. 编译型 vs. 延迟绑定
Python 首先会被编译成一种中间的字节码(pyc),然后再执行。所以,Python 的运行过程是先编译再解释。不过,很多使用 Python 很久的人说,Python 是一种“后期绑定”的语言,不应该简单地称它为解释型语言。
那么,Python 和其他解释型语言有什么不同呢?
在 Python 的上下文中,“后期绑定”是什么意思呢?
Java 是另一种语言,它的源代码也是先编译成字节码,然后再执行。
Java 是一种解释型语言还是编译型语言呢?
在编译和执行方面,Java 和 Python 有什么不同呢?
有人说 Java 没有“后期绑定”。这和 Java 程序比 Python 稍微快一点有什么关系吗?
如果你能给我一些已经讨论过这个话题的链接,那就太好了;我很想多了解一下。谢谢!
5 个回答
我们说的 绑定时间 和 解释/编译 这两个概念之间有联系。
绑定时间就是一个符号表达式和它具体值关联起来的时间。这和编程语言的定义有关,比如变量的动态作用域和静态作用域,或者静态方法和虚拟方法,动态类型和静态类型之间的区别。
接下来就是语言的实现了。越多的信息在一开始就能确定,写编译器就越简单。反过来,如果语言的绑定时间越晚,编写编译器就越困难。因此,有时候我们需要依赖解释技术。
不过,这两者之间的区别并不是绝对的。我们可以认为所有东西最终都是被解释的(参见 S.Lott 的回答),而且代码的一部分可以被编译、反编译或动态重新编译(比如 JIT),这让两者的界限变得模糊。
举个例子,Java 中的动态类加载就属于“晚绑定”这一类:类的集合并不是一成不变的,可以动态加载类。当我们知道类的集合时,可以进行一些优化,但一旦加载了新类,这些优化就需要失效。更新方法时,调试基础设施也会出现类似情况:JVM 需要取消优化所有曾经内联过该方法的调用点。
我对 Python 了解不多,但 Python 的开发者可能更喜欢用“晚绑定”这个词,以避免混淆。
Python和其他解释型语言有什么不同呢?
这个问题有点复杂。解释型语言和像C#这样的“管理代码”语言,以及虚拟机语言(比如Java),其实是一个奇怪的连续体。有些人甚至会说所有语言都是“解释型”的——包括机器语言。毕竟,CPU的电子电路也在“解释”机器语言。
简单来说,“解释型”意味着有一层可见的软件在解释你的应用程序的字节码。而“非解释型”则意味着你的软件是(或多或少)直接由底层硬件执行的。至于“管理代码”的人们,可以继续讨论这个细节。
能告诉我在Python中“晚绑定”是什么意思吗?
变量没有被声明为某种类型。变量会在尽可能晚的时候与某种类型绑定——也就是在赋值给一个实际对象的时候。
Java是解释型还是编译型语言?
是的。Java会被编译成字节码,然后这些字节码会被解释。我更倾向于称其为解释型。
不过,有些人会(出于一些很奇怪的原因)不同意这个观点。只要有任何形式的“编译”步骤——即使是最小的——总会让人感到困惑。字节码的转换几乎与程序在运行时的实际行为没有关系。有些人喜欢说只有那些完全没有任何“编译”前处理的语言才能被称为解释型。现在这样的例子不多了,因为很多语言都是从人类友好的文本转换为解释器友好的字节码。甚至在80年代的Applesoft Basic中,输入代码时也会进行这样的转换。
一些JVM会进行即时编译(JIT),而有些则不会,还有一些是混合的。说JVM只做JIT字节码转换是不准确的。有些JVM会这样做,有些则不会。
在编译/执行方面,Java和Python有什么不同吗?
其实没有什么不同。Java虚拟机可以执行Python代码。[为了避免混淆,这里提到的“python”并不是指“python源代码”,而是指python字节码。]
据说Java没有“晚绑定”。这和Java程序比Python稍快有什么关系吗?
可能有关系。Java程序通常更快是因为JIT编译器在运行时将Java字节码转换为机器码。
静态(“早”)绑定对Java的好处并不像对C或C++这样的真正编译语言那样明显,因为后者几乎没有任何运行时检查。Java仍然会进行数组边界检查,而C则为了追求速度而省略了这一步。
实际上,“晚绑定”并没有太大的性能损失。Python的属性和方法是通过简单的字典查找来解析的。字典是一种哈希结构,性能相当不错。名称的哈希值可以放入一个“内部”字符串字面量池中,从而分摊计算哈希的成本。
如果想要更有趣的内容,可以看看PyPy和RPython。这是一个可以进行JIT编译的Python解释器。你会得到一个两层的解释器。你的代码由PyPy解释,而PyPy又是由RPython解释的。http://alexgaynor.net/2010/may/15/pypy-future-python/
晚绑定是一个和解释执行完全不同的概念。
严格来说,解释型语言是直接从源代码执行的。它不会经过字节码编译的阶段。之所以会让人困惑,是因为Python程序本身就是一个解释器,但它解释的是字节码,所以我们可以说Python的字节码语言是“被解释的”。而Python语言本身其实是经过编译的。
相比之下,Java字节码现在既是被解释的也是被编译的。它会通过一个叫做JIT编译器的工具编译成本地代码,然后直接在硬件上运行。
晚绑定是类型系统的一种特性,几乎所有语言在某种程度上都有这个特性,无论它们是解释型的还是编译型的。