2012-04-14 5 views
1

Es gibt ein Tutorial an http://pythonprogramming.jottit.com/functional_programming und es gibt ein Beispiel, wie Sie mit Funktionen höherer Ordnung zuweisen Funktionen zurückzukehren:Ist es möglich, Rückgabewert von zwei Funktionen höherer Ordnung auf die gleiche Variable in Python [siehe Details]

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 

und

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

aber ich habe nicht, wie es in der Lage ist, zwei Funktionen auf denselben variablen auf den Aussagen zuzuordnen:

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

scheinen sowohl Trace als auch Memoize auf den letzten Aufruf zu wirken. Warum das?

+1

„beide Spur und memoize scheinen Wirkung auf den letzten Aufruf zu haben“ Sie wurden beide angerufen. Noch Fragen? –

Antwort

2

Sowohl trace() als auch memoize() erstellen ein neues Funktionsobjekt und geben es an Sie zurück.

In jedem Fall "wickelt" das neue Funktionsobjekt das alte Funktionsobjekt ein, so dass die ursprüngliche Funktion nicht verloren geht.

Fähigkeiten meiner erstaunlichen ASCII-Art verwenden, hier ist ein Diagramm:

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 

Wir mit einem Funktionsobjekt mit dem Namen fib gebunden beginnen.

Dann rufen wir trace(fib), die ein neues Funktionsobjekt erstellt. Wenn es zuerst erstellt wird, lautet sein Name g, aber wir binden es dann an den Namen fib. Versuchen Sie, fib.__name__ zu drucken.

Dann rufen wir memoize(fib), die ein neues Funktionsobjekt erstellt. Wieder wird es zuerst mit dem Namen g erstellt, dann aber an den Namen fib gebunden.

Denken Sie daran, in Python ist alles ein Objekt, und Objekte können ohne Namen, mit einem Namen oder mit vielen Namen existieren. In diesem Fall verwenden wir den Namen fib weiter, binden ihn aber immer wieder an verschiedene Funktionsobjekte an.

2

Es ist nicht anders als:

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

Wie a um 7 erhöht haben, fib werden beide Dekorateure auf sie angewendet haben.

+0

Sorry @Ignacio die obige Analogie fühlt sich anders an als die Frage für mich.In Ihrem Fall wird a durch einen neuen Wert "überschrieben"; Ich bekomme nichts mehr. Vielleicht muss ich über Dekorateure nachlesen. Ich dachte, dass beide Funktionen neue generieren und fib würde bei der zweiten Aufgabe überschrieben werden. Kannst du mir sagen, was hinter den Kulissen passiert? –

+0

'fib' wird überschrieben. Dass sie einen Verweis auf das Objekt haben, das fib * used enthielt, ist nur Flusen. –

+0

Wie führt es dann beide Jobs (Trace, Memoize) aus? –

3

Was Sie geschrieben haben, ist sehr ähnlich zu

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

weil Sie geändert haben, die die Variable fib Punkte nach dem Aufruf funktionieren trace, so memoize wird auf die Tracing-Version angewendet (und dann fib ist "überschrieben" erneut).

Wenn Sie eine Tracing-Version und eine memoized Version separat haben wollen, müssen Sie ihre Ergebnisse zu verschiedenen Variablen zuzuweisen, zB:

fib_trace = trace(fib) 
fib_memo = memoize(fib) 
print fib_trace(4), fib_memo(4)