让我们有一个方法,会缓存它计算的结果。
"如果 "方法:
def calculate1(input_values):
if input_values not in calculate1.cache.keys():
# do some calculation
result = input_values
calculate1.cache[input_values] = result
return calculate1.cache[input_values]
calculate1.cache = {}
"例外 "办法:
def calculate2(input_values):
try:
return calculate2.cache[input_values]
except AttributeError:
calculate2.cache = {}
except KeyError:
pass
# do some calculation
result = input_values
calculate2.cache[input_values] = result
return result
"gethas "方法:
def calculate3(input_values):
if not hasattr(calculate3, cache):
calculate3.cache = {}
result = calculate3.cache.get(input_values)
if not result:
# do some calculation
result = input_values
calculate3.cache[input_values] = result
return result
是否有另一种(更快)方法?哪种方法最快捷?拟态? 你会用哪个?
笔记: 有一个速度的差异。
calculate = calculateX # depening on test run
for i in xrange(10000):
calculate(datetime.utcnow())
结果 time python test.py
:
calculate1: 0m9.579s
calculate2: 0m0.130s
calculate3: 0m0.095s
使用一个 收藏品.defaultdict. 它正是为此目的而设计的。
当然,这毕竟是 Python。只要用一个 违约金.
好吧,如果你想追忆一些东西,最好使用Memoize类和装饰器。
class Memoize(object):
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
if args not in self.cache:
self.cache[args] = self.func(*args)
return self.cache[args]
现在定义一些要被备忘的函数,比如说一个键加强函数,它可以完成一个字符串哈希值的100,000个md5sums。
import md5
def one_md5(init_str):
return md5.md5(init_str).hexdigest()
@Memoize
def repeat_md5(cur_str, num=1000000, salt='aeb4f89a2'):
for i in xrange(num):
cur_str = one_md5(cur_str+salt)
return cur_str
这个 @Memoize
函数装饰器相当于先定义函数,然后再定义 repeat_md5 = Memoize(repeat_md5)
. 你第一次调用它的特定参数集时,函数需要大约一秒钟的时间来计算;而下一次你调用它的时候,它几乎是瞬时的,因为它从缓存中读取。
至于记忆化的方法;只要你不做一些傻事(比如第一个方法中你做的是 if key in some_dict.keys()
而非 if key in some_dict
)应该不会有太大的区别。 (第一种方法很糟糕,因为你先从字典中生成一个数组,然后检查键是否在其中;而不是仅仅检查键是否在dict中(见 像Python爱好者一样编码)). 另外,从本质上来说,捕获异常会比if语句慢(你必须创建一个异常,然后异常处理程序必须处理它;然后你再捕获它)。