Python解释器可以优化哪些东西?

dan*_*451 2 python optimization interpreter

我认为由于懒惰的评估语句,例如:

if True and True (...):
    # do something
Run Code Online (Sandbox Code Playgroud)

...应该True and在 Python 解释器的部分之后立即跳过。但是,与编译后的代码相比,我认为 Python 解释器不能优化像显式布尔比较这样的坏风格,对吧?

if condition == True:
    # do something
Run Code Online (Sandbox Code Playgroud)

编译器会对此进行优化并删除该== True部分,但解释器总是要评估哪些语句在该condition ==部分之后等待,从而在== True每次执行代码时进行不必要的比较?!

是否存在更多这样的陷阱,解释器无法优化代码?我知道最后一个问题很开放,但我想确实存在一些流行的例子吗?

Mat*_*lia 6

编译本身并不多(CPython 确实编译为字节码),但是语言的极端动态特性阻碍了“传统”优化,这些优化由在 Python 编译时难以检查的不变量引导,因为语言的语义是这样的,关于代码实际应该做什么的大多数信息只在运行时可用。

你的if condition == True:例子是一个很好的例子:只有当编译器可以证明它condition始终是一个布尔值时,才能优化比较,如果它是从当前范围内的文字以外的任何东西派生出来的,那么这是一项重要的任务 - 如果它可以证明,在运行时,没有人设法True用其他东西覆盖(可能只在 Python 2 IIRC 中)。

请注意,某些类型推断是可能的,这实际上是 Jedi 等代码完成工具的工作方式;然而,Jedi 可以采取一些捷径并假设某种标准环境,而解释器必须应对语言允许的对全局变量的最奇怪的修改。

所以,一般来说,CPython 不会非常努力地优化任何东西——实际上,它似乎没有做任何“智能”代码分析,AFAICT 他们主要尝试构建一个高效但“主要是普通”的解释器。因此,期望为您编写的内容支付几乎完全相同的费用,没有优化器可以保存草率的代码。

顺便说一句,您的and示例不是解释器完成的优化,它只是定义运算符语义的方式(并且指定它andor进行短路评估非常重要,它不是可选的“优化”,因为它如果右手操作数有副作用,则可能会改变程序的可观察行为)。

对于动态语言更好的方法是使用跟踪 JIT代替跟踪 JIT - 解释器让代码运行一段时间,并观察似乎保持良好的不变量(例如,condition似乎总是一个布尔值,True总是True,一些变量始终是一个整数,...),然后使用此信息将代码的优化版本编译为机器代码。只要上述不变量成立,就可以运行它 - 但是一旦用于编译优化版本的前提之一被破坏,执行就会返回到解释模式,并且再次开始跟踪以找出是否有新的优化版本可以建。

因此,典型情况得到了很好的优化,应用了通常的优化技术,但是每当发生奇怪的事情(但语言允许)时,运行时可以回退到常规的“文字”字节码解释。

这是用于从大多数动态语言中获得良好性能的方法(大多数现代 JavaScript 引擎使用这种基本方法的一些变体),并且在 Python 中用于 PyPy。