1

http://pythonprogramming.jottit.com/functional_programmingにチュートリアルがあり、高階関数を使用して関数を返す方法の例を示しています。

def trace(f):
    f.indent = 0
    def g(x):
        print '|  ' * f.indent + '|--', f.__name__, x
        f.indent += 1
        value = f(x)
        print '|  ' * f.indent + '|--', 'return', repr(value)
        f.indent -= 1
        return value
    return g

def memoize(f):
    cache = {}
    def g(x):
        if x not in cache:
            cache[x] = f(x)
        return cache[x]
    return g

しかし、ステートメントの同じ変数に2つの関数を割り当てる方法がわかりません:

fib = trace(fib)
fib = memoize(fib)
print fib(4)

trace と memoize の両方が最後の呼び出しに影響を与えているようです。何故ですか?

4

3 に答える 3

3

あなたが書いたものは非常に似ています

fib2 = memoize(trace(fib))
print fib2(4)

の呼び出し後に変数がfib指す関数を変更したtraceためmemoize、トレース バージョンに適用されます (その後、fib再び「上書き」されます)。

トレース バージョンとメモ化バージョンを別々に使用する場合は、それらの結果を異なる変数に割り当てる必要があります。たとえば、次のようになります。

fib_trace = trace(fib)
fib_memo = memoize(fib)
print fib_trace(4), fib_memo(4)
于 2012-04-14T04:24:24.090 に答える
2

それは以下と違いはありません:

a = a + 2
a = a + 5
print a

a7 増加したように、fib両方のデコレータが適用されます。

于 2012-04-14T04:17:22.067 に答える
2

両方とも新しい関数オブジェクトを作成し、それを返しますtrace()memoize()

いずれの場合も、新しい関数オブジェクトが古い関数オブジェクトを「ラップ」するため、元の関数は失われません。

私の驚くべき ASCII アートのスキルを使用して、これが図です。

f(x)   # this is your original function

trace(f(x))   # trace "wraps" it and returns a wrapped object

memoize(trace(f(x)))   # memoize "wraps" it and returns a new wrapped function object

name にバインドされた関数オブジェクトから始めますfib

trace(fib)次に、新しい関数オブジェクトを作成するを呼び出します。最初に作成されたとき、その名前は ですgが、次に名前にバインドしfibます。印刷してみてくださいfib.__name__

memoize(fib)次に、新しい関数オブジェクトを作成するを呼び出します。繰り返しますが、最初は の名前で作成されますgが、次に name にバインドされfibます。

Python ではすべてがオブジェクトであり、オブジェクトは名前なし、1 つの名前、または複数の名前で存在できることを思い出してください。この場合、名前を再利用しfib続けますが、別の関数オブジェクトで再バインドし続けます。

于 2012-04-14T04:23:43.647 に答える