2010-07-31 45 views
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()') 
+0

你在談論「Python裝飾器」和memoization是他們的一個奇妙的用途。它不需要evals(這是部分邪惡的;你已經聽到了正確的)。 – msw 2010-07-31 07:36:30

回答

13

您可以記住,而不必訴諸於eval

A(非常基本的)memoizer:

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) 
5

eval經常拼錯爲evil,主要是因爲在運行時執行 「串」 的想法充滿了安全方面的考慮。你有沒有足夠的逃避代碼?引號?還有一些令人煩惱的頭痛。你的記憶處理程序的作品,但它並不是Python的做事方式。 MAK的方法更爲Pythonic。讓我們嘗試一些實驗。

我編輯了兩個版本,並使它們只用100次輸入運行一次。我也搬出了Memoizer的實例。 以下是結果。

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

除此之外,你的版本需要一個圍繞被記憶的函數的包裝,它應該被寫入一個字符串。這很醜陋。 MAK的解決方案是乾淨的,因爲「memoisation」過程被封裝在一個單獨的功能中,可以方便地應用於任何昂貴的功能,而且不顯眼。這不是Pythonic。如果您有興趣,我可以在我的Python教程http://nibrahim.net.in/self-defence/上編寫這樣的裝飾器。