Python功能评估效率

aar*_*qli 4 python

如果我这样做:

x=[(t,some_very_complex_computation(y)) for t in z]
Run Code Online (Sandbox Code Playgroud)

显然some_very_complex_computation(y)不依赖于t.所以它应该只评估一次.有没有办法让Python意识到这一点,所以它不会为每次迭代评估some_very_complex_computation(y)?

编辑:我真的想在一行中做到这一点......

Nik*_* B. 7

通常你应该遵循San4ez的建议,并在这里使用一个临时变量.在某些情况下,我仍然会提出一些可能有用的技巧:

通常,如果要为子表达式绑定名称(这通常是为什么需要临时变量),可以使用lambda:

x = (lambda result=some_very_complex_computation(y): [(t, result) for t in z])()
Run Code Online (Sandbox Code Playgroud)

在这种特殊情况下,以下是一个非常干净和可读的解决方案:

x = zip(z, itertools.repeat(some_very_complex_computation(y)))
Run Code Online (Sandbox Code Playgroud)

关于这些自动优化的一般说明

在像Python这样的动态语言中,实现将非常难以确定它some_very_complex_computation引用透明的,也就是说,它将始终为相同的参数返回相同的结果.如果你想要那样的魔术,你可能想要研究像Haskell这样的函数式语言.

"明确的"纯洁:记忆

但是你可以做的是some_very_complex_computation显式缓存它最近参数的返回值:

from functools import lru_cache

@lru_cache()
def some_very_complex_computation(y):
  # ...
Run Code Online (Sandbox Code Playgroud)

这是Python 3.在Python 2中,你必须自己编写装饰器:

from functools import wraps

def memoize(f):
  cache = {}
  @wraps(f)
  def memoized(*args):
    if args in cache:
      return cache[args]
    res = cache[args] = f(*args)
    return res
  return memoized

@memoize
some_very_complex_computation(x):
  # ...
Run Code Online (Sandbox Code Playgroud)