解释型 vs. 编译型 vs. 后期绑定
Python被编译成中间字节码(pyc)然后执行。因此,先有编译,后有解释。然而,Python 的长期用户表示 Python 是一种“后期绑定”语言,不应该将其称为解释性语言。
Python 与其他解释语言有何不同?
您能告诉我“后期绑定”在 Python 上下文中的含义吗?
Java 是另一种首先将源代码编译为字节码,然后解释为字节码的语言。
Java 是一种解释/编译语言吗?
在编译/执行方面与Python有何不同?
据说 Java 没有“后期绑定”。这与 Java 程序比 Python 稍快有什么关系吗?
如果您也能给我链接到人们已经讨论过这个问题的地方,那就太好了;我很想阅读更多相关内容。谢谢。
Python is compiled into an intermediate bytecode(pyc) and then executed. So, there is a compilation followed by interpretation. However, long-time Python users say that Python is a "late-binding" language and that it should`nt be referred to as an interpreted language.
How would Python be different from another interpreted language?
Could you tell me what "late-binding" means, in the Python context?
Java is another language which first has source code compiled into bytecode and then interpreted into bytecode.
Is Java an interpreted/compiled language?
How is it different from Python in terms of compilation/execution?
Java is said to not have, "late-binding". Does this have anything to do with Java programs being slighly faster than Python?
It'd be great if you could also give me links to places where people have already discussed this; i'd love to read more on this. Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这涉及到吹毛求疵。解释性语言和“托管代码”语言(例如 C# 和虚拟机语言(例如 Java))形成了一个奇怪的连续体。有人会说所有语言都是“解释型”的——甚至是机器语言。毕竟,CPU 的电子电路“解释”机器语言。
您能做的最好的事情就是说“解释”意味着有一个可见的软件层解释您的应用程序字节码。 “未解释”意味着您的软件(或多或少)由底层硬件直接执行。 “托管代码”的人可以自由地继续分裂这根头发。
变量未声明为具有类型。变量尽可能晚地绑定到类型——通过实际对象的赋值。
是的。它被编译为字节码。字节码被解释。我更喜欢称其为解释型。
然而,人们会(出于非常模糊的原因)不同意。任何类型的“编译”步骤的存在——无论多么小——总是让人感到困惑。字节码的翻译与程序在运行时的实际行为几乎没有关系。有些人喜欢说,只有那些完全没有任何预处理“编译”污染的语言才能被解释。这样的例子已经不多了,因为许多语言都是从人类友好的文本翻译成解释器友好的字节码。甚至 Applesoft Basic(早在 80 年代)就在您键入代码时完成了这种转换过程。
一些 JVM 执行 JIT。有些则不然。有些是混合物。说 JVM 只进行 JIT 字节码翻译是不正确的。有些 JVM 可以。有些则不然。
一点也不。 Java虚拟机可以执行Python。 [对于容易混淆的人来说,本文中的“python”一词不可能意味着“python 源”。它一定是指 python 字节码。]
也许。 Java 程序通常速度更快,因为 JIT 编译器在运行时将 Java 字节代码转换为机器代码。
静态(“早期”)绑定对于 Java 来说没有像 C 或 C++ 这样的真正编译语言那样的好处,在这些语言中几乎没有任何类型的运行时检查。 Java 仍然执行诸如数组边界检查之类的操作,而 C 出于原始速度的考虑而省略了这些操作。
实际上,“晚”绑定几乎没有什么惩罚。 Python 属性和方法是使用简单的字典查找来解析的。字典是一个哈希;性能相当不错。名称的哈希值可以放入“interned”字符串文字池中,以分摊计算哈希值的成本。
如果想要真正的乐趣,请查看 PyPy 和 RPython。这是一个可以进行JIT编译的Python解释器。您最终会得到一个二级口译员。您的代码由 PyPy 解释。 PyPy 由 RPython 解释。 http://alexgaynor.net/2010/may/15/pypy-future -python/
That involves hair-splitting. Interpreted languages and "managed code" languages like C# and virtual machine languages (like Java) form a weird continuum. There are folks who will say that all languages are "interpreted" -- even machine language. After all, the electronic circuits of the CPU "interpret" machine language.
The best you can do is say that "interpreted" means there's a visible layer of software interpreting your application byte-codes. "not-interpreted" means that your software is (more-or-less) directly executed by the underlying hardware. "Managed code" people are free to continue to split this hair.
Variables are not declared to have a type. The variable is bound to a type as late as possible -- with the assignment of an actual object.
Yes. It's compiled to byte codes. The byte codes are interpreted. I prefer to call it interpreted.
However, people will (for really obscure reasons) disagree. The presence of any kind of "compile" step -- however minimal -- always confuses people. The translation to byte code has almost no relevance to the actual behavior of the program at run time. Some folks like to say that only languages that are totally free from any taint of pre-processing "compilation" can be interpreted. There aren't a lot of examples of this any more, since many languages are translated from human-friendly text to interpreter friendly byte codes. Even Applesoft Basic (back in the 80's) had this kind of translation pass done as you typed code in.
Some JVM's do JIT. Some don't. Some are a mixture. To say that the JVM only does JIT byte-code translation is incorrect. Some JVM's do. Some don't.
Not at all. The Java VM can execute Python. [For the easily-confused, the word "python" in this context cannot possibly mean "python source". It must mean python bytecode.]
Perhaps. Java programs are often faster because of JIT compilers that translate Java byte code to machine code at run-time.
Static ("early") binding doesn't have the same kind of benefit for Java that it has with a truly compiled language like C or C++ where there are almost no run-time checks of any kind. Java still does things like array bounds checking, which C omits in the interest of raw speed.
There is actually little penalty for "late" binding. Python attributes and methods are resolved using simple dictionary lookups. The dictionary is a hash; performance is quite good. The hashes for names can be put into an "interned" string literal pool amortizing the cost of computing the hash.
For real fun, look PyPy and RPython. This is a Python interpreter that can do JIT compilation. You wind up with a 2-tier interpreter. Your code is interpreted by PyPy. PyPy is interpreted by RPython. http://alexgaynor.net/2010/may/15/pypy-future-python/
后期绑定是一个与解释非常不同的概念。
严格来说,解释型语言是直接从源代码执行的。它不经过字节码编译阶段。之所以会出现这种混乱,是因为 python 程序是一个解释器,但它解释字节码,因此您可以将其描述为“解释型”,这是 Python 的字节码语言。 Python语言本身是一种编译语言。
相比之下,如今 Java 字节码既可以解释又可以编译。它由 JIT 编译器编译为本机代码,然后直接在硬件上运行。
后期绑定是类型系统的一个属性,并且在某种程度上存在于大多数语言中,无论它们是解释的还是编译的。
Late binding is a very different concept to interpretation.
Strictly speaking, an interpreted language is executed directly from source. It doesn't go through a byte-code compilation stage. The confusion arises because the python program is an interpreter, but it interprets the byte-code, so it is Python's byte-code language that you would describe as "interpreted". The Python language itself is a compiled language.
Java bytecode, in contrast, is both interpreted and compiled, these days. It is compiled into native code by a JIT-compiler and then run directly on the hardware.
Late binding is a property of the type system and is present in most languages to some degree, regardless of whether they are interpreted or compiled.
我们所说的绑定时间和解释/编译的概念之间存在联系。
绑定时间是符号表达式与其具体值绑定的时间。这与编程语言的定义更相关,例如变量的动态与静态作用域。或者静态方法与虚拟方法或动态类型与静态类型。
然后是语言的实现。预先静态了解的信息越多,编写编译器就越容易。反之,语言的束缚越晚,难度就越大。因此有时需要依赖解释技术。
然而两者之间的区别并不严格。我们不仅可以认为一切都是最终解释的(参见S.Lott的答案),而且部分代码可以动态编译、反编译或重新编译(例如JIT),使得区别非常模糊。
例如,Java中的动态类加载属于“后期绑定”类别:类的集合不是一次性固定的,类可以动态加载。当我们知道类集时,可以进行一些优化,但一旦加载新类,就需要使其失效。使用调试基础设施更新方法的能力也会发生同样的情况:JVM 将需要取消优化所有内联方法的调用站点。
我对 Python 了解不多,但 Python 从业者可能更喜欢术语“后期绑定”以避免这种混淆。
There's a connection between what we call the binding time and the concept of interpretation/compilation.
The binding time is the time when a symbolic expression is bound to its concrete value. That's more related to the definition of programming language, e.g. dynamic vs. static scoping of variables. Or static method vs. virtual methods or dynamic typing vs. static typing.
Then comes the implementation of the language. The more information are statically known upfront, the easier it is to write a compiler. Inversely, the more late bound the language is, the harder it is. Hence the need to rely on interpretive techniques sometimes.
The distinction between both isn't strict however. Not only can we consider that everything is ultimately interpreted (see S.Lott answer), but part of the code can be compiled, decompile, or recompile dynamically (e.g. JIT) making the distinction very fuzzy.
For instance, dynamic class loading in Java goes in the category "late binding": the set of class is not fixed once for all, and classes can be loaded dynamically. Some optimizations can be done when we know the set of classes, but will need to be invalidated once a new classes is loaded. The same happens with the ability to update a method with the debugging infrastructure: the JVM will need to de-optimize all call sites were the method had been inlined.
I don't know much about Python, but Python practitioners prefer maybe the term "late bound" to avoid such confusion.
我认为在编译 Java 时解释 Python 的常见误解是因为 Java 有一个显式的编译步骤 - 您必须运行 javac 将 .java 源文件转换为可以运行的 .class 字节码文件。
正如您正确地指出的那样,Python 类似地将源文件编译为字节码,但它是透明地进行的 - 编译和运行通常是在一个步骤中完成的,因此对用户来说不太明显。
重要的区别在于早期和晚期之间。后期绑定和动态&静态类型。编译/解释的区别是毫无意义且无关紧要的。
I think the common misconception that Python is interpreted while Java is compiled arises because Java has an explicit compilation step - you have to run javac to convert your .java source file into a .class bytecode file that can be run.
As you rightly point out Python similarly compiles source files into bytecode but it does it transparently - compiling and running is generally done in a single step so it is less obvious to the user.
The important difference is between early & late binding and dynamic & static typing. The compiled/interpreted distinction is meaningless and irrelevant.
绑定时间是名称被解析为事物的时间。
更动态的语言倾向于后期绑定。
这可以与解释/编译分开——例如,
与 C++ 相比,objective-C 方法的解析较晚且动态。
Java 在类加载时完成大部分绑定:晚于 C,但是
早于Python。
我最喜欢的 Stan Kelly-Bootle 的《计算机矛盾》中的一句话:
绑定时间 n。哈希表损坏的那一刻。
==>计算的进步可以与“绑定的迟到”相对应,这让我思考我自己所谓的CS所谓的职业:金色的过去,灰色的现在和玫瑰色的未来。这是我对 Synge 乐观主义的看法:除了 t=0 之外,草更绿。在 EDSAC I 上,我的函数(5ch 纸带子例程)在输入前大约两周被打孔、拼接和装订。这被称为过早捆绑,需要灵活地使用松紧带。接下来,FORTRAN 带来了一种新的装订方式:湿漉漉的一副纸牌,拒绝洗牌。然后使用 Algol 和 C,我喜欢静态(编译时)绑定,直到 C++ 带来了动态(运行时)绑定的麻木乐趣。我目前的研究旨在将绑定延迟到执行后很久。我将这种现象称为末日捆绑,正如圣马太福音中所预言的那样:“……凡你在地上捆绑的,在天上也必被捆绑……”(马太福音 16:19 KJV)。
binding time is when names get resolved to things.
More dynamic languages tend towards late binding.
This can be separate from interpretation/compilation -- for example,
objective-C methods are resolved late and dynamically compared to C++.
Java does much of it's binding at class load time : later than C but
earlier than Python.
my favorite quote from Stan Kelly-Bootle's Computer Contradictionary:
binding time n. The moment when the hash table becomes corrupted.
==> Advances in computing can be mapped against the "lateness of binding," which has me thinking about my own so-called CS so-called career: golden past, gray present, and rosy future. This is my version of Synge's optimism: the grass is greener except at t=0. On EDSAC I, my functions (5ch paper-tape subroutines) were punched, spliced, and bound about two weeks before input. This is known aspremature binding and calls for deftness with elastic bands. FORTRAN came next with a new kind of binding: soggy decks of cards that refused to be shuffled. Then with Algol and C, I enjoyed static (compile-time) binding, until C++ brought the numbing joys of dynamic (run-time) binding. My current research aims at delaying the binding until well after execution. I call this end-time binding, as prophesied in St. Matthew's Gospel: "...and whatsoever thou shalt bind on earth shall be bound in heaven..." (Matthew 16:19 KJV).