10

メモ化プロセスを処理できる以下のようなクラスを作成することは「良い習慣」ですか? メモ化の利点は非常に大きいため (この例のように、関数呼び出しが 501003 秒から 1507 秒に減少し、コンピューターの CPU 時間が 1.409 秒から 0.006 秒に減少する場合もあります)、このようなクラスが役立つと思われます。

ただし、の使用に関する否定的なコメントしか読んだことがありません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 を入力として 1 回だけ実行するようにしました。のインスタンス化も外しました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 に答える