13

Python被编译成中间字节码(pyc)然后执行。因此,有一个编译,然后是解释。但是,长期使用 Python 的用户说 Python 是一种“后期绑定”语言,不应将其称为解释语言。

  1. Python 与另一种解释语言有何不同?

  2. 你能告诉我在 Python 上下文中“后期绑定”是什么意思吗?

Java 是另一种语言,它首先将源代码编译成字节码,然后再解释成字节码。

  1. Java 是解释/编译语言吗?

  2. 在编译/执行方面它与 Python 有何不同?

  3. 据说Java没有“后期绑定”。这是否与 Java 程序比 Python 快一点有关?

如果您也可以给我链接到人们已经讨论过的地方,那就太好了;我很想阅读更多关于此的内容。谢谢你。

4

5 回答 5

9

Python 与另一种解释语言有何不同?

这涉及到头发分裂。解释语言和“托管代码”语言(如 C#)和虚拟机语言(如 Java)形成了一个奇怪的连续体。有些人会说所有语言都是“解释的”——甚至是机器语言。毕竟,CPU 的电子电路“解释”机器语言。

你能做的最好的就是说“解释”意味着有一个可见的软件层解释你的应用程序字节码。“未解释”意味着您的软件(或多或少)由底层硬件直接执行。“托管代码”的人可以自由地继续分裂这个头发。

你能告诉我在 Python 上下文中“后期绑定”是什么意思吗?

变量未声明为具有类型。变量尽可能晚地绑定到一个类型——分配一个实际的对象。

Java 是解释/编译语言吗?

是的。它被编译成字节码。字节码被解释。我更喜欢称它为解释性的。

然而,人们会(出于非常模糊的原因)不同意。任何类型的“编译”步骤的存在——无论多么小——总是让人们感到困惑。字节码的转换与程序在运行时的实际行为几乎没有关系。有些人喜欢说只有完全没有任何预处理“编译”污染的语言才能被解释。这样的例子已经不多了,因为许多语言都从对人类友好的文本翻译成对解释器友好的字节码。甚至 Applesoft Basic(早在 80 年代)在您输入代码时也完成了这种翻译通行证。

一些 JVM 执行 JIT。有些没有。有些是混合物。说 JVM 只做 JIT 字节码翻译是不正确的。一些JVM会这样做。有些没有。

在编译/执行方面它与 Python 有何不同?

一点也不。Java VM 可以执行 Python。[对于容易混淆的,这个上下文中的“python”这个词不可能意味着“python 源”。它一定是指 python 字节码。]

据说Java没有“后期绑定”。这是否与 Java 程序比 Python 快一点有关?

也许。Java 程序通常更快,因为 JIT 编译器在运行时将 Java 字节码转换为机器码。

静态(“早期”)绑定对 Java 的好处与它对真正编译的语言(如 C 或 C++)的好处不同,后者几乎没有任何类型的运行时检查。Java 仍然执行数组边界检查之类的操作,而 C 出于原始速度的考虑而将其省略。

实际上,“迟到”绑定几乎没有惩罚。Python 属性和方法使用简单的字典查找来解析。字典是一个哈希;性能相当不错。名称的散列可以放入“interned”字符串文字池中,分摊计算散列的成本。

为了真正有趣,看看 PyPy 和 RPython。这是一个可以进行 JIT 编译的 Python 解释器。你最终得到了一个 2 层的解释器。您的代码由 PyPy 解释。PyPy 由 RPython 解释。 http://alexgaynor.net/2010/may/15/pypy-future-python/

于 2010-05-21T11:22:25.997 回答
7

后期绑定是一个与解释非常不同的概念。

严格来说,解释语言是直接从源代码执行的。它不经过字节码编译阶段。出现混淆是因为 python 程序一个解释器,但它解释字节码,所以它是 Python 的字节码语言,您可以将其描述为“解释”。Python 语言本身是一种编译语言。

相比之下,如今 Java 字节码既可以解释也可以编译。它由 JIT 编译器编译为本机代码,然后直接在硬件上运行。

后期绑定是类型系统的一个属性,并且在某种程度上存在于大多数语言中,无论它们是解释的还是编译的。

于 2010-05-21T11:24:29.877 回答
3

我们所说的绑定时间解释/编译的概念之间存在联系。

绑定时间是符号表达式绑定到其具体值的时间。这与编程语言的定义更相关,例如变量的动态与静态范围。或静态方法与虚拟方法或动态类型与静态类型。

然后是语言的实现。预先静态知道的信息越多,编写编译器就越容易。相反,语言越晚绑定,就越难。因此,有时需要依赖解释技术。

然而,两者之间的区别并不严格。我们不仅可以认为一切最终都会被解释(参见 S.Lott 的答案),而且部分代码可以动态编译、反编译或重新编译(例如 JIT),这使得区别非常模糊。

例如,Java 中的动态类加载属于“后期绑定”类别:类集不是一劳永逸的,类可以动态加载。当我们知道类集时可以进行一些优化,但是一旦加载了新类,就需要使其无效。使用调试基础设施更新方法的能力也是如此:如果方法已内联,JVM 将需要取消优化所有调用站点。

我对 Python 了解不多,但 Python 从业者可能更喜欢“后期绑定”一词以避免这种混淆。

于 2010-05-21T11:48:51.203 回答
2

我认为在编译 Java 时解释 Python 的常见误解出现了,因为 Java 有一个显式的编译步骤——你必须运行 javac 来将你的 .java 源文件转换为可以运行的 .class 字节码文件。

正如您正确指出的那样,Python 类似地将源文件编译为字节码,但它是透明的 - 编译和运行通常在一个步骤中完成,因此对用户来说不太明显。

重要的区别在于早期和晚期绑定以及动态和静态类型之间。编译/解释的区别是没有意义和不相关的。

于 2010-05-21T15:34:26.270 回答
0

绑定时间是名称被解析为事物的时间。更动态的语言倾向于后期绑定。这可以与解释/编译分开——例如,与 C++ 相比,objective-C 方法的解析较晚并且是动态的。Java 在类加载时完成了大部分绑定:晚于 C 但早于 Python。

我最喜欢 Stan Kelly-Bootle 的 Computer Contradictionary 中的一句话

绑定时间 n. 哈希表损坏的时刻。

==> 计算的进步可以映射到“绑定的迟到”,这让我想到了我自己所谓的 CS 所谓的职业:金色的过去,灰色的现在和美好的未来。这是我对 Synge 乐观主义的看法:除了 t=0,草更绿了。在 EDSAC I 上,我的函数(5ch 纸带子程序)在输入前大约两周被打孔、拼接和绑定。这被称为过早绑定并且需要使用松紧带的灵巧性。FORTRAN 紧随其后,推出了一种新的装订方式:湿漉漉的纸牌,拒绝洗牌。然后使用 Algol 和 C,我喜欢静态(编译时)绑定,直到 C++ 带来动态(运行时)绑定的麻木乐趣。我目前的研究旨在将绑定延迟到执行之后。正如圣马太福音中所预言的那样,我称之为末世的约束:“......

于 2010-05-21T15:34:10.787 回答