Vor kurzem habe ich angefangen, mit Python herumzuspielen, und bin auf etwas Besonderes gestoßen, wie Verschlüsse funktionieren. Betrachten Sie den folgenden Code:
adders=[0,1,2,3]
for i in [0,1,2,3]:
adders[i]=lambda a: i+a
print adders[1](3)
Es wird ein einfaches Array von Funktionen erstellt, die eine einzelne Eingabe verwenden und die durch eine Zahl hinzugefügte Eingabe zurückgeben. Die Funktionen sind in einer for
Schleife aufgebaut, in der der Iterator i
von 0
bis ausgeführt wird 3
. Für jede dieser Zahlen wird eine lambda
Funktion erstellt, die sie erfasst i
und zur Eingabe der Funktion hinzufügt. Die letzte Zeile ruft die zweite lambda
Funktion mit 3
als Parameter auf. Zu meiner Überraschung war die Ausgabe 6
.
Ich habe a erwartet 4
. Meine Argumentation war: In Python ist alles ein Objekt und daher ist jede Variable ein wesentlicher Zeiger darauf. Beim Erstellen der lambda
Closures für habe i
ich erwartet, dass ein Zeiger auf das Integer-Objekt gespeichert wird, auf das aktuell verwiesen wird i
. Das bedeutet, dass beim i
Zuweisen eines neuen Ganzzahlobjekts die zuvor erstellten Abschlüsse nicht beeinflusst werden sollten. Leider zeigt die Überprüfung des adders
Arrays in einem Debugger, dass dies der Fall ist. Alle lambda
Funktionen beziehen sich auf den letzten Wert i
, zeigt 3
, deren Ergebnisse in der adders[1](3)
Rückkehr 6
.
Was mich über Folgendes wundern lässt:
- Was erfassen die Verschlüsse genau?
- Was ist die eleganteste Methode, um die
lambda
Funktionen davon zu überzeugen , den aktuellen Wert voni
auf eine Weise zu erfassen , die nicht beeinflusst wird, wenni
sich ihr Wert ändert?
i
verlässt man den Namespace?
print i
das nach der Schleife nicht funktionieren würde. Aber ich habe es selbst getestet und jetzt verstehe ich, was du meinst - es funktioniert. Ich hatte keine Ahnung, dass Schleifenvariablen nach dem Schleifenkörper in Python verweilten.
if
, with
, try
usw.