Memoization Handler
创建一个像下面这样的类来处理你的记忆过程,这是"好的实践"吗?memoization的好处是如此之大(在某些情况下,比如这一个,它从501003下降到1507个函数调用,在我的计算机上从1.409下降到0.006秒的CPU时间),以至于看起来像这样的类是有用的。
不过,我只看了关于
这可以自动保存任何返回值,但会损失副作用。谢谢。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | import cProfile class Memoizer(object): """A handler for saving function results.""" def __init__(self): self.memos = dict() def memo(self, string): if string in self.memos: return self.memos[string] else: self.memos[string] = eval(string) self.memo(string) def factorial(n): assert type(n) == int if n == 1: return 1 else: return n * factorial(n-1) # find the factorial of num num = 500 # this many times times = 1000 def factorialTwice(): factorial(num) for x in xrange(0, times): factorial(num) return factorial(num) def memoizedFactorial(): handler = Memoizer() for x in xrange(0, times): handler.memo("factorial(%d)" % num) return handler.memo("factorial(%d)" % num) cProfile.run('factorialTwice()') cProfile.run('memoizedFactorial()') |
你不用求助于
一个(非常基本的)记忆器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def memoized(f): cache={} def ret(*args): if args in cache: return cache[args] else: answer=f(*args) cache[args]=answer return answer return ret @memoized def fibonacci(n): if n==0 or n==1: return 1 else: return fibonacci(n-1)+fibonacci(n-2) print fibonacci(100) |
我编辑了两个版本,并让它们以100作为输入只运行一次。我还移动了
1 2 3 4 | >>> timeit.timeit(memoizedFactorial,number=1000) 0.08526921272277832h >>> timeit.timeit(foo0.mfactorial,number=1000) 0.000804901123046875 |
除此之外,您的版本还需要在要Memoised的函数周围有一个包装器,该包装器应该写在一个字符串中。那太难看了。MAK的解决方案是干净的,因为"记忆过程"被封装在一个单独的功能中,可以方便地以一种不引人注目的方式应用于任何昂贵的功能。这不是很Python。在我的Python教程http://nibrahim.net.in/self-defense/中,我有一些关于编写此类装饰的详细信息,以防您感兴趣。