基本上,python 使用语言解析器解释代码行......然后将解析的行编译为字节码。这个字节码是“编译的python”。
让我们编写一些代码:
# file: foo.py
class Bar(object):
x = 1
def __init__(self, y):
self.y = y
现在我们导入它。
>>> import foo
>>> foo
<module 'foo' from 'foo.py'>
>>> reload(foo)
<module 'foo' from 'foo.pyc'>
您会注意到,我们第一次导入foo 时,它说它是从foo.py 导入的。那是因为 python 必须将代码字节编译成模块对象。但是,这样做会在您的目录中留下一个 .pyc 文件......这是一个编译的 python 文件。 Python 更喜欢使用编译后的代码,作为一种节省时间的方式,而不是再次编译代码......所以当你 reload 模块时,python 会选择要导入的编译后的代码。基本上,当你“安装”python 模块时,你只是将编译后的代码移动到 python 可以导入它的地方(在你的 PYTHONPATH 上)。
>>> import numpy
>>> numpy
<module 'numpy' from '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/__init__.pyc'>
site-packages 目录是安装已编译的第 3 方代码的默认位置。实际上,模块只是文件的 python 对象表示。意思是,模块实例是一个编译文件。一旦你将文件“编译”到一个模块中,它就不再关心文件中的内容......python只需要在那之后编译的字节码。
>>> import types
>>> types.ModuleType.mro()
[<type 'module'>, <type 'object'>]
>>> foo.__class__.mro()
[<type 'module'>, <type 'object'>]
>>> i = object()
>>> object
<type 'object'>
>>> i
<object object at 0x1056f60b0>
在这里我们看到(使用types)foo 是ModuleType 的一个实例...所以基本上是一个编译文件。 mro 显示模块继承自 python object,这是 python 中的主要对象。 (是的,它是面向对象的)。
这里i 是object 的一个实例,就像foo 是ModuleType 的一个实例一样。 Python 使用编译对象的实例,而不是底层代码......就像(几乎?)所有其他语言一样。因此,当您使用在 foo 模块中构建的类时,您正在使用该类的字节编译实例。您可以通过动态添加方法来动态修改类实例...它不会更改基础文件foo.py...但它确实会更改模块foo的字节编译实例保存在内存中。
>>> zap = foo.Bar(2)
>>> zap.x, zap.y
(1, 2)
>>> foo.Bar
<class 'foo.Bar'>
>>> foo.Bar.mro()
[<class 'foo.Bar'>, <type 'object'>]
>>>
>>> def wow(self):
... return self.x + self.y
...
>>> wow(zap)
3
>>> foo.Bar.wow = wow
>>> foo.Bar.wow(zap)
3
>>> zap.wow()
3
同样,文件foo.py 将保持不变......但是,我将wow 添加到类Bar,所以它就像wow 首先在代码中一样可用。因此,使用“已编译的”python 根本不是静态的……它只是意味着您正在使用经过字节编译的代码,以便在您第一次导入它时节省一些时间。请注意,由于模块 foo 是一个实例,您还可以在内存中编辑它(不仅仅是已经存在于其内容中的对象)。
>>> foo.square = lambda x:x**2
>>>
>>> from foo import square
>>> square(3)
9
在这里,我将squared 添加到foo——不是添加到foo.py,而是添加到内存中foo 的字节编译副本。
那么你能在编译后的代码中腌制和取消腌制对象吗?绝对地。如果您使用过pickle,您可能已经这样做了。
附:如果您正在谈论构建 python 的 C++ 扩展,并将代码编译到共享库......它仍然基本上没有什么不同。
如果您正在寻找有关字节编译的详细信息,请在此处查看我的问题和答案:How is a python function's name reference found inside it's declaration?。