存储函数值以防止再次 运行

store values of function to prevent from running again

假设我有一些复杂的函数f(fvar1, ..., fvarN)例如:

def f(fvar1,..., fvarN):
    return (complicated function of fvar1, ..., fvarN).

现在函数 g(gvar1, ..., gvarM) 有一个表达式 f(fvar1, ..., fvarN),比方说:

def g(gvar1, ..., gvarM):
    return stuff * f(gvar1 * gvar2, ..., gvar5 * gvarM) - stuff * f(gvar3, gvar2, ..., gvarM)

其中 gf 的参数可以是 gvar1, ..., gvarM.

的不同线性组合

因为f是一个复杂的函数,调用f的代价很大,但是也很难将值存储在g中,因为g有许多 f 具有不同参数组合的实例。

有没有办法 存储 f 值,这样就不会一次又一次地调用相同值的 f 而不必定义每个值f 在本地 g?

的不同实例

是的,这叫做记忆。基本思想是让 f() 根据传入的参数维护某种数据存储。然后,如果使用 相同的 参数调用它,它只需 returns 存储的值而不是重新计算它。

数据存储可能需要限制大小并针对您预期的调用模式进行优化,方法是根据某些规则删除参数集。例如,如果使用参数集的 number 次表明它将来可能被使用,您可能想要删除不常使用的模式,并保留那些使用频率更高的模式经常。

例如,考虑以下 Python 两个数字相加的代码(假设这是一个非常耗时的操作):

import random

def addTwo(a, b):
    return a + b

for _ in range(100):
    x = random.randint(1, 5)
    y = random.randint(1, 5)
    z = addTwo(x, y)
    print(f"{x} + {y} = {z}")

这行得通,但是,如果您使用与之前相同的数字,当然效率会很低。您可以按如下方式添加备忘。

代码将“记住”一定数量的计算(可能是随机的,给定字典,但我不保证)。如果它得到一对它已经知道的,它只是returns缓存的值。

否则,它计算该值,将其存储到缓存中,并确保所述缓存不会变得太大:

import random, time

# Cache, and the stats for it.

(pairToSumMap, cached, calculated) = ({}, 0, 0)

def addTwo(a, b):
    global pairToSumMap, cached, calculated

    # Attempt two different cache lookups first (a:b, b:a).

    sum = None
    try:
        sum = pairToSumMap[f"{a}:{b}"]
    except:
        try:
            sum = pairToSumMap[f"{b}:{a}"]
        except:
            pass

    # Found in cache, return.

    if sum is not None:
        print("Using cached value: ", end ="")
        cached += 1
        return sum

    # Not found, calculate and add to cache (with limited cache size).

    print("Calculating value: ", end="")
    calculated += 1

    time.sleep(1) ; sum = a + b # Make expensive.

    if len(pairToSumMap) > 10:
        del pairToSumMap[list(pairToSumMap.keys())[0]]
    pairToSumMap[f"{a}:{b}"] = sum
    return sum

for _ in range(100):
    x = random.randint(1, 5)
    y = random.randint(1, 5)
    z = addTwo(x, y)
    print(f"{x} + {y} = {z}")

print(f"Calculated {calculated}, cached {cached}")

您会看到我还添加了 cached/calculated 信息,包括显示正在运行的缓存的最终统计行,例如:

Calculated 29, cached 71

我还使计算成为一项昂贵的操作,因此您可以看到它的实际效果(根据输出速度)。缓存的会立即返回,计算总和需要一秒钟。