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 forSchleife aufgebaut, in der der Iterator ivon 0bis ausgeführt wird 3. Für jede dieser Zahlen wird eine lambdaFunktion erstellt, die sie erfasst iund zur Eingabe der Funktion hinzufügt. Die letzte Zeile ruft die zweite lambdaFunktion mit 3als 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 lambdaClosures für habe iich erwartet, dass ein Zeiger auf das Integer-Objekt gespeichert wird, auf das aktuell verwiesen wird i. Das bedeutet, dass beim iZuweisen eines neuen Ganzzahlobjekts die zuvor erstellten Abschlüsse nicht beeinflusst werden sollten. Leider zeigt die Überprüfung des addersArrays in einem Debugger, dass dies der Fall ist. Alle lambdaFunktionen 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
lambdaFunktionen davon zu überzeugen , den aktuellen Wert voniauf eine Weise zu erfassen , die nicht beeinflusst wird, wennisich ihr Wert ändert?
iverlässt man den Namespace?
print idas 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, tryusw.