compile
是 exec
和 eval
的低级版本。它不执行或评估你的语句或表达式,但返回一个可以执行它们的代码对象。模式如下:
compile(string, '', 'eval')
返回代码对象,该对象将在执行 eval(string)
时执行。请注意,你不能在此模式下使用语句;只有(单个)表达式有效。compile(string, '', 'exec')
返回代码对象,该对象将在执行 exec(string)
时执行。你可以在此处使用任意数量的语句。compile(string, '', 'single')
类似于 exec
模式,但它将忽略除第一条语句以外的所有内容。请注意,带有其结果的 if
/else
语句被认为是单个语句。更新:
何时编译 Python?
通常情况下,编译 Python 可以利用性能。已编译的代码具有更快的启动时间,因为它不必编译,但它不会运行更快。
最重要的是,如果你想手动将代码转换成字节码,则应使用 compile
。这引出了另一个重要但相关的问题为什么要这样做?
正如在这篇杰出的文章中所提到的:
如果要使用 exec 并且计划多次执行该代码,请确保将其先编译为字节码,然后仅在新字典(即命名空间)中执行该字节码。
值得注意的是:
现在执行字节码相比于创建并执行字节码会快多少呢? $ python -mtimeit -s 'code = "a = 2; b = 3; c = a * b"' 'exec code' 10000次循环,最好的3次结果:每次22.7微秒 $ python -mtimeit -s 'code = compile("a = 2; b = 3; c = a * b","", "exec")' 'exec code' 1000000次循环,最好的3次结果:每次0.765微秒 对于一个非常短的代码示例来说,速度快了32倍。但是,当代码量增加时,情况会变得更糟。为什么?因为将Python代码解析并转换为字节码是一项昂贵的操作,与评估字节码相比。当然,这也影响到了execfile,它完全不使用字节码缓存,它怎么可能呢?如果您传递foo.py文件的路径,它不会神奇地检查是否有.pyc文件。https://github.com/mitsuhiko/jinja2/blob/master/jinja2/environment.py#L506
与之相比,例如django.template,在“用户空间”中执行变量查找等操作(再次强调,这只是个比喻,有点奇怪)。https://github.com/django/django/blob/master/django/template/base.py#L752
exec
内置函数时才真正有用。感谢您花时间阐明这个话题。 - Adam Lewis