Lokale Variablen in verschachtelten Funktionen
Okay, Bär mit mir, ich weiß, es sieht furchtbar kompliziert, aber bitte helfen Sie mir zu verstehen, was geschieht.
from functools import partial
class Cage(object):
def __init__(self, animal):
self.animal = animal
def gotimes(do_the_petting):
do_the_petting()
def get_petters():
for animal in ['cow', 'dog', 'cat']:
cage = Cage(animal)
def pet_function():
print "Mary pets the " + cage.animal + "."
yield (animal, partial(gotimes, pet_function))
funs = list(get_petters())
for name, f in funs:
print name + ":",
f()
Gibt:
cow: Mary pets the cat.
dog: Mary pets the cat.
cat: Mary pets the cat.
Also im Grunde, warum bin ich nicht immer drei verschiedene Tiere? Ist das nicht die cage
'verpackt' in den lokalen Umfang der verschachtelten Funktion? Wenn nicht, wie funktioniert ein Aufruf an die verschachtelte Funktion suchen die lokalen Variablen?
Ich weiß, dass das laufen in diese Art von Problemen in der Regel bedeutet, man ist 'etwas falsch', aber ich würde gerne verstehen, was passiert.
Versuchen
for animal in ['cat', 'dog', 'cow']
... ich bin sicher, wird jemand kommen und erklären, dies obwohl - es ist ein Python-gotcha 🙂InformationsquelleAutor noio | 2012-09-14
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die verschachtelte Funktion sieht Variablen aus dem parent scope wenn es ausgeführt wird, nicht, wenn definiert.
Den Rumpf der Funktion wird kompiliert, und die "freie" Variablen (nicht in der Funktion definiert sich durch Abtretung), die verifiziert sind, dann gebunden als Verschluss-Zellen um die Funktion, mit der der code über einen index referenzieren jede Zelle.
pet_function
so hat eine freie variable (cage
) die dann verwiesen wird, über eine Schließung Zelle mit dem index 0. Der Verschluss selbst Punkte auf die lokale variablecage
imget_petters
Funktion.Wenn Sie tatsächlich die Funktion aufrufen, dass diese Schließung wird dann verwendet, um den Wert von
cage
in den umgebenden Bereich beim Aufruf der Funktion. Hier liegt das problem. Durch den Aufruf von Funktionen, dieget_petters
Funktion ist bereits getan computing ist es Ergebnisse. Diecage
lokale variable an einem gewissen Punkt während der Ausführung zugewiesen wurde jede der'cow'
,'dog'
, und'cat'
Saiten, aber am Ende der Funktioncage
enthält, dass der Letzte Wert'cat'
. So, wenn Sie rufen jede der dynamisch zurückgegeben Funktionen, erhalten Sie den Wert'cat'
gedruckt.Den work-around ist, um sich nicht auf die Verschlüsse. Sie können eine partielle Funktion erstellen Sie stattdessen eine neue Funktion Rahmen, oder binden Sie die variable als eine default-Wert für ein Schlüsselwort-parameter.
Partielle Funktion Beispiel, mit
functools.partial()
:Erstellung eines neuen Bereichs Beispiel:
Bindung der Variablen als default-Wert für ein Schlüsselwort-parameter:
Gibt es keine Notwendigkeit zu definieren, die
scoped_cage
Funktion in der Schleife, die Zusammenstellung erfolgt nur einmal, nicht bei jeder iteration der Schleife.InformationsquelleAutor Martijn Pieters
Mein Verständnis ist, dass der Käfig gesucht wird in der übergeordneten Funktion namespace, wenn die ergab pet_function eigentlich heißt, nicht vor.
Also, wenn Sie
Erzeugen Sie 3 Funktionen, die die zuletzt geschaffenen Käfig.
Wenn Sie ersetzen Ihre Letzte Schleife mit :
Erhalten Sie tatsächlich :
InformationsquelleAutor Nicolas Barbey
Dies ergibt sich aus der folgenden
nach der Iteration wird der Wert von
i
ist faul gespeichert als endgültiger Wert.Als generator die Funktion funktionieren würde (D. H. drucken Sie den jeweiligen Wert in turn), aber bei der Umwandlung auf eine Liste, es läuft über den generator, damit alle Anrufe an
cage
(cage.animal
) return Katzen.InformationsquelleAutor Andy Hayden