10

创建一个像下面这样可以为您处理记忆过程的类是“好习惯”吗?memoization 的好处是如此之大(在某些情况下,比如这个,它在我的计算机上从 501003 到 1507 个函数调用以及从 1.409 到 0.006 秒的 CPU 时间),看起来像这样的一个类会很有用。

但是,我只阅读了关于eval(). 考虑到这种方法提供的灵活性,这种用法是否可以原谅?

这可以以失去副作用为代价自动保存任何返回值。谢谢。

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()')
4

2 回答 2

14

您无需借助eval.

一个(非常基本的)记忆器:

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)
于 2010-07-31T07:37:50.807 回答
5

eval 经常拼错evil主要是因为在运行时执行“字符串”的想法充满了安全考虑。您是否充分地转义了代码?引号?还有许多其他恼人的头痛。您的 memoise 处理程序有效,但它确实不是 Python 的做事方式。MAK 的方法更像 Pythonic。让我们尝试一些实验。

我编辑了两个版本,让它们只运行一次,输入为 100。我还移出了Memoizer. 这是结果。

>>> timeit.timeit(memoizedFactorial,number=1000)
0.08526921272277832h
>>> timeit.timeit(foo0.mfactorial,number=1000)
0.000804901123046875

除此之外,您的版本需要对要记忆的函数进行包装,该函数应以字符串形式编写。太丑了 MAK 的解决方案是干净的,因为“记忆过程”被封装在一个单独的函数中,可以方便地以不显眼的方式应用于任何昂贵的函数。这不是很 Pythonic。如果您有兴趣,我在http://nibrahim.net.in/self-defence/的 Python 教程中有一些关于编写此类装饰器的详细信息。

于 2010-07-31T08:08:57.267 回答