低级编译语言和性能
@hpaulj 和@jeevcat 的答案是正确的。
但Python是否被编译的故事更复杂。
首先,确实写得好的C++代码比写得好的 Python代码快得多。而且编译后的代码一般可以加快计算速度。
但原因不是因为代码被编译,本身。这是因为这些编译语言通常也是低级语言,可以让您直接操作内存、避免垃圾收集等。此外,允许 Python 动态性和简单性,一切都是对象。因此,例如,Python 列表是一个对象,其中包含对“分散”在整个内存中的其他对象的引用列表。这(显然)比列表中所有值彼此相邻的内存块的计算效率低。
而且,正如其他人所提到的,Python 代码只是调用(对话)这个其他更高效的 C 代码。
Python 编译了吗?
但是还有一个更有趣的问题。 Python 是否已编译?一些人可能会无意中声称它没有被编译。严格来说,这不是真的。任何时候您导入一个包或模块,如果它还没有被编译,它将被不可见地编译并保存。 (您可能甚至不会注意到任何编译发生。)
您可以看到这种情况:任何.pyc 文件(以.pyc 而不是.py 结尾的文件)都是编译后的Python 文件。尝试在编辑器中或通过cat 打开.pyc 文件。你会看到它是一个二进制文件,看起来像乱码。
看已编译 Python 代码的隐形创建
如何创建编译好的 Python 代码?
假设您有以下文件夹结构:
❯ tree -L 1
.
├── __pypackages__ # This is a folder, the rest are files
├── addressbook.proto
├── addressbook_pb2.py
├── pdm.lock
├── protobuf-python-3.17.3.tar.gz
├── pyproject.toml
└── readme.txt
(以上结构包含 Python Google Protocol Buffer 示例,使用现代 PDM package manager 结构。)
我们可以看到唯一的 Python 模块(文件)是 addressbook_pb2。所以,让我们导入那个文件:
❯ python
Python 3.9.7 (default, Oct 13 2021, 06:45:31)
[Clang 13.0.0 (clang-1300.0.29.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import addressbook_pb2
>>> [exit out of Python]
❯
除了快速导入文件(模块)addressbook_pb2.py,我什么也没做。但只是这个简单的导入创建了一个名为__pycache__ 的完整“已编译代码文件夹”,其中包含已编译模块:
❯ tree -L 1
.
├── __pypackages__
├── __pycache__ # This is the folder that was auto-generated
├── addressbook.proto
├── addressbook_pb2.py
├── pdm.lock
├── protobuf-python-3.17.3.tar.gz
├── pyproject.toml
└── readme.txt
现在我们来看看 __pycache__ 文件夹中有什么:
❯ ll __pycache__ # `ll` is my shortcut for `ls -al`, it's a common shortcut
total 8
drwxr-xr-x 3 mikewilliamson staff 96B Oct 30 21:43 .
drwxr-xr-x 34 mikewilliamson staff 1.1K Oct 30 21:43 ..
-rw-r--r-- 1 mikewilliamson staff 3.2K Oct 30 21:43 addressbook_pb2.cpython-39.pyc
❯
请注意文件addressbook_pb2.cpython-39.pyc 在那里。词干是模块的名称 (addressbook_pb2)。但它也有 .cpython-39.pyc 扩展名。这告诉我们一些事情:
- 它是编译后的代码……这就是
.pyc 结尾的意思
- 它是使用
cpython-39编译的,意思是它是Python(最普遍的)版本3.9的CPython“风味”。