Python解释器可以优化哪些内容?

3

我认为由于“惰性求值”等语句:

if True and True (...):
    # do something

在Python解释器中,True and 部分之后的内容应该会被跳过。然而,与编译代码相比,我认为Python解释器无法优化明确的布尔比较这种不良风格,对吗?

if condition == True:
    # do something

一个编译器会优化这个,删除 == True 部分,但是解释器每次执行代码都必须评估在 condition == 部分后面等待的语句, 因此会做不必要的比较 == True ?! 还有其他类似的问题吗?即使我知道这个问题比较开放,但是我猜一些常见的例子是存在的?

6
如果在Python中if conditionif condition == True是等价的,那么编译器会很容易地将它们转换为彼此。但是这种转换不会发生,因为这两个代码片段并不等价。有一件事,如果你尝试在C中这样做,你会得到完全相同的问题;许多不等于True的值都被认为是真。 - user2357112
3
考虑 if 2 == True: ...if 2: ... 之间的区别。 - juanpa.arrivillaga
C语言直到C99才引入了内置的布尔类型。仍然有很多代码在if语句中使用其他类型,或者像#DEFINE BOOL char这样做,甚至<stdbool.h>true定义为1 - user2357112
好的,我确实必须问一下:为什么这很重要呢?如果你在运行解释性代码,为什么你要关心操作码级别的优化? - spectras
@Qlstudio:因为这个问题非常宽泛,而且信息随时可能发生变化。这不是适合在Stack Overflow上提问的好问题。 - user2357112
显示剩余3条评论
1个回答

7
它并不是很注重编译(CPython会将代码编译成字节码),但是该语言极具动态特性,阻碍了“传统”优化,这些优化通过在编译时检查难以确定的不变量进行指导,在Python中大多数关于代码实际执行的信息只有在运行时才能获得,因此在Python中的编译时难以检查。你提到的if condition == True: 是一个很好的例子,只有当编译器可以证明condition总是布尔值时,才能对比较进行优化,如果它源自当前范围内除文字面值之外的任何东西,这是一个非常麻烦的任务 - 如果在运行时,没有人管理覆盖True的内容,这仅在Python 2中可能发生。 请注意,某些类型推断是可能的,这实际上是像Jedi这样的代码完成工具的工作方式;但是,Jedi可以采取一些捷径,例如假设某种标准环境,而解释器必须处理语言允许的全局变量的最奇怪的修改。

因此,总体而言,CPython 并不会尝试非常努力地优化任何内容 - 实际上,据我所知,它似乎并不会进行任何“智能”代码分析,而是努力构建一个有效但“基本上是通用”的解释器。 因此,期望为你写的代码付出几乎相同的代价,没有优化器可以节省草率的代码。

顺便说一下,你的and示例不是解释器执行的优化,只是操作符语义定义的方式(它非常关键,因为它指定andor具有短路评估并且这不是可选的“优化”,因为如果右操作数具有副作用,则可能会改变程序的可观察行为)。

对于这种动态语言,更好的方法是使用跟踪JIT - 解释器让代码运行一段时间,并观察看起来保持良好的不变量(例如,condition似乎总是布尔值,True总是 True,某些变量总是整数等等),然后使用此信息将优化版本的代码编译为机器代码。只要满足上述不变量,该版本就可以运行很长时间 - 但是,一旦用于编译优化版本的先决条件被打破,执行就会回到解释模式,并重新进行跟踪以找出是否可以构建新的优化版本。

因此,典型情况得到了很好的优化,应用了通常的优化技术,但是每当发生一些奇怪的事情(但是语言允许),运行时就可以回退到常规“文字”字节码解释。 这是从大多数动态语言中挤出良好性能的方法(大多数现代JavaScript引擎使用此基本方法的某些变体),在Python中也用于PyPy。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接