为什么 Cpython 是 C 写的,而不是 Python
CPython 中的 C 是指 C 语言,意味着这个 Python 默认发行版是用 C 语言编写的。其实,CPython 的编译器是用纯 C 语言编写的,或者是 C 和 Python 的组合。那我们不经要问:
为什么 Cpython 不是用其他语言
我们首先要知道,高级语言都要编译为机器语言。所以区别就在于编译器的工作方式中,有两种类型的编译器:
-
自我实现编译器:如 Go 语言,一开始也是 C 语言实现的编译器,后面逐渐使用 Go 重写编译器;
-
源到源编译器:是用另一种已经有编译器的语言编写的编译器。开发新语言时用已经完善且成熟的编译器编写,节省时间和学习成本。
Python 解释器中默认和最流行实现是 CPython 。使用它有一个重要的优势。C 是编译语言,其代码转换为机器代码,由中央处理单元(CPU)直接执行。
为什么 Python 最常见的解释器是 C 语言编写的,那为什么不是 Python 或者 C++ 等编程语言呢?
这是一种实用和历史原因的组合。(主要是)历史原因是 CPython 1.0 于 1989 年发布。当时,C 最近是标准化的。C ++几乎是未知的并且明确不可移植,因为几乎没有人有 C ++编译器。
Linux 之父 —— Linus Torvalds 无敌不喜欢 C ++,并且多次向 C++ 表示抗议。
Python 之父 Guido 也没有表示对 C ++ 的那种强烈的负面情绪。
尽管 C++ 在今天更广泛且更容易获得,但将 CPython 重写为与 C++ 兼容的 C 仍需要大量工作。就其本身而言,这项工作几乎没有或根本没有真正的好处。
并非百分百的 C
C(CPython)中的 Python 实现不是 100% 编译的,也不是 100% 解释的。在运行 Python 脚本的过程中,既有编译也有解释。为了清楚起见,让我们看看运行 Python 脚本的步骤:
-
使用 CPython 编译源代码生成字节码
-
在 CPython 解释器中解释字节码
-
在 CPython 虚拟机中运行 CPython 解释器的输出
当 CPython 编译源代码(.py 文件)来生成 CPython 字节码(.pyc 文件)时,会进行编译。然后使用 CPython 解释器解释 CPython 字节码(.pyC 文件),输出在 CPython 虚拟机中运行。根据上述步骤,运行 Python 脚本的过程同时涉及编译和解释。
CPython 编译器仅生成一次字节码,但每次代码运行时都会调用解释器。通常对字节码的解释需要很多时间。如果使用解释器慢下来,为什么要使用它?大的原因是它有助于使 Python 跨平台。由于字节码在 CPU 的顶部的 CPython 虚拟机中运行,因此它独立于它运行的机器。因此,字节码可以不变地运行不同的机器。
CPython 保持其 C 的传统:许多标准库模块,如 ssl
模块或 sockets
模块,都是用 C 写好的,用以访问底层操作系统 API。Windows 和 Linux 内核中用于创建网络 sockets 的 API、使用文件系统和与显示交互的都用 C 编写。
Python 专注于 对 C 语言层面上的扩展。
如果没有使用解释器,那么 CPython 编译器将生成直接在 CPU 中运行的机器代码。因为不同平台有不同的指令,所以代码不会跨平台。
总之,使用编译器加快过程,但解释器使代码跨平台。因此,Python 比 C 慢的原因是使用解释器。请记住,编译器刚刚运行一次,但每次执行代码时都会运行解释器。
Python 比 C 慢得多,但许多程序员仍然更喜欢它,因为它更容易使用。Python 从程序员隐藏了许多细节,这可以帮助防止令人沮丧的调试。例如,由于 Python 是一种动态键入的语言,您不必明确指定代码中的每个变量的类型 – Python 将自动推断出来。相比之下,具有静态类型语言(如 C,C ++ 或 Java),您必须指定变量的类型,如下所示。
int x = 2022 string s = "Hello, World"
将此与以下 Python 中的实现进行比较。动态类型使编码更容易,但增加了机器寻找合适数据类型的负担。这会使过程变慢。
x = 2022 s = "Hello, World"
一般来说,像 Python 这样的“更高级别”语言更容易用于开发人员。但是,当运行代码时,需要将其转换为低级指令。简单易用的这种转换带来的牺牲是需要更多的时间。
如果时间是一个重要因素,那么您需要使用较低级别的指令。比如直接使用 C 语言、C++ 或者时兴的 Rust。
总结
当然,如今,CPython 不再是唯一的 Python 实现。还有如下的 Python 解释器:
-
Stackless Python(支持微线程的 CPython 分支)
-
IronPython(在 .NET 上运行的 Python)
-
Jython(在 Java 虚拟机上运行的 Python)
-
PyPy(带有 JIT 编译器的快速 python 实现)
-
RPython(Python 的静态类型子集)编写的 PyPy
-
NQP 和 PIR 中的 Pynie 等等
总结就是众多的历史原因让吉多大叔选择了用 C 语言写出 Python 的解释器,而 Python 的设计原则为了追求简洁的语法牺牲了一定的时间,所以官方默认的解释起依旧是 CPython。
而为了开发者的方便,时至今日,还有更多其他的解释器版本,而不是弃用原有的 CPython 的底层 API ,选择用 Python 自我实现的解决方案。
好了,这就是为什么 CPython 不用其他语言实现的原因了,希望您看到这里能有帮助。
下一篇文章见!
灵感来源:https://realpython.com/cpython-source-code-guide/
本文文字及图片出自 InfoQ
你也许感兴趣的:
- 【外评】电脑从哪里获取时间?
- 【外评】为什么 Stack Overflow 正在消失?
- Android 全力押注 Rust,Linux 却在原地踏步?谷歌:用 Rust 重写固件太简单了!
- 【外评】哪些开源项目被广泛使用,但仅由少数人维护?
- 【外评】好的重构与不好的重构
- C 语言老将从中作梗,Rust for Linux 项目内讧升级!核心维护者愤然离职:不受尊重、热情被消耗光
- 【外评】代码审查反模式
- 我受够了维护 AI 生成的代码
- 【外评】Linux 桌面市场份额升至 4.45
- 【外评】作为全栈开发人员如何跟上 AI/ML 的发展?
你对本文的反应是: