即使我在理解 CPython、JPython、IronPython、PyPy 之间有何不同时也遇到了同样的问题。
所以,在我开始解释之前,我愿意澄清三件事:
- Python:它是一种语言,它只说明/描述如何向解释器(接受您的 Python 代码的程序)传达/表达自己。
- 实施:这完全是关于解释器是如何编写的,特别是用什么语言以及它最终会做什么。
- 字节码:它是由程序处理的代码,通常被称为虚拟机,而不是由“真正的”计算机机器,硬件处理器。
CPython 是用 C 语言编写的实现。它最终生成特定于 Python 的字节码(基于堆栈机器的指令集),然后执行它。将 Python 代码转换为字节码的原因是,如果解释器看起来像机器指令,则它更容易实现。但是,没有必要在执行 Python 代码之前生成一些字节码(但 CPython 确实会生成)。
如果您想查看 CPython 的字节码,那么您可以。您可以这样做:
>>> def f(x, y): # line 1
... print("Hello") # line 2
... if x: # line 3
... y += x # line 4
... print(x, y) # line 5
... return x+y # line 6
... # line 7
>>> import dis # line 8
>>> dis.dis(f) # line 9
2 0 LOAD_GLOBAL 0 (print)
2 LOAD_CONST 1 ('Hello')
4 CALL_FUNCTION 1
6 POP_TOP
3 8 LOAD_FAST 0 (x)
10 POP_JUMP_IF_FALSE 20
4 12 LOAD_FAST 1 (y)
14 LOAD_FAST 0 (x)
16 INPLACE_ADD
18 STORE_FAST 1 (y)
5 >> 20 LOAD_GLOBAL 0 (print)
22 LOAD_FAST 0 (x)
24 LOAD_FAST 1 (y)
26 CALL_FUNCTION 2
28 POP_TOP
6 30 LOAD_FAST 0 (x)
32 LOAD_FAST 1 (y)
34 BINARY_ADD
36 RETURN_VALUE
现在,让我们看看上面的代码。第 1 到 6 行是函数定义。在第 8 行,我们导入了“dis”模块,该模块可用于查看由 CPython(解释器)生成的中间 Python 字节码(或者你可以说,Python 字节码的反汇编程序)。
注意:我从#python IRC 频道获得了此代码的链接:https ://gist.github.com/nedbat/e89fa710db0edfb9057dc8d18d979f9c
然后是 Jython,它是用 Java 编写的,最终生成 Java 字节码。Java 字节码在 Java 运行时环境中运行,它是 Java 虚拟机 (JVM) 的一种实现。如果这令人困惑,那么我怀疑您不知道 Java 是如何工作的。通俗地说,Java(语言,而不是编译器)代码由 Java 编译器获取并输出一个文件(即 Java 字节码),该文件只能使用 JRE 运行。这样做是为了,一旦 Java 代码被编译,就可以以 Java 字节码格式移植到其他机器上,该格式只能由 JRE 运行。如果这仍然令人困惑,那么您可能想看看这个网页。
在这里,您可能会问 CPython 的字节码是否像 Jython 一样可移植,我怀疑不是。在 CPython 实现中生成的字节码是特定于该解释器的,以便于进一步执行代码(我也怀疑,这种中间字节码生成只是为了便于在许多其他解释器中完成处理)。
因此,在 Jython 中,当您编译 Python 代码时,您最终会得到可以在 JVM 上运行的 Java 字节码。
同样,IronPython(用 C# 语言编写)将您的 Python 代码编译为公共语言运行时 (CLR),这是一种与 JVM 类似的技术,由 Microsoft 开发。