我以为替换以下代码可以提高性能:
def f(a, b):
return math.sqrt(a) * b
result = []
a = 100
for b in range(1000000):
result.append(f(a, b))
和:
def g(a):
def f(b):
return math.sqrt(a) * b
return f
result = []
a = 100
func = g(a)
for b in range(1000000):
result.append(func(b))
我假设由于执行关闭时
a
是固定的,所以解释器将预先计算涉及a
的所有内容,因此math.sqrt(a)
将重复一次,而不是重复1000000次。我的理解是否总是正确的,或者总是不正确的,或者是正确/不正确的,取决于实现方式?
我注意到
func
的代码对象是在运行时之前构建的(至少在CPython中),并且是不可变的。然后,该代码对象似乎使用全局环境来实现关闭。这似乎表明我希望进行的优化没有发生。 最佳答案
这个假设是错误的,我不知道它是从哪里来的。闭包仅捕获变量绑定(bind),在您的情况下,它捕获a
的值,但这并不意味着发生了更多的魔术操作:每次调用math.sqrt(a)
时,表达式f
仍将求值。
毕竟,每次都必须计算它,因为解释器不知道sqrt
是“纯”的(返回值仅取决于参数,并且没有副作用)。像您期望的那样的优化在函数式语言中是可行的(引用透明性和静态类型在这里有很大帮助),但是很难在Python中实现,这是一种强制性的动态类型的语言。
就是说,如果您想预先计算math.sqrt(a)
的值,则需要明确地执行以下操作:
def g(a):
s = math.sqrt(a)
def f(b):
return s * b
return f
或使用
lambda
:def g(a):
s = math.sqrt(a)
return lambda b: s * b
现在
g
实际上返回了一个带有1个参数的函数,您只需要用一个参数调用结果即可。