存储函数值以防止再次 运行
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)
其中 g
中 f
的参数可以是 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
我还使计算成为一项昂贵的操作,因此您可以看到它的实际效果(根据输出速度)。缓存的会立即返回,计算总和需要一秒钟。
假设我有一些复杂的函数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)
其中 g
中 f
的参数可以是 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
我还使计算成为一项昂贵的操作,因此您可以看到它的实际效果(根据输出速度)。缓存的会立即返回,计算总和需要一秒钟。