2016-04-06 23 views
5

Ich habe einen Hintergrund von C++ und versuchen, etwas Python zu lernen.Late Binding Python Verschlüsse

Whist ich verstehe virtuelle Funktionen für C++, ich verstehe leider nicht, was mit späten Bindung von Schließungen in Python gemeint ist.

-Link: https://gist.github.com/deemson/8efabf56d67623ead804

Copy-Pasta aus einem Tutorial:

functions = [] 
for n in [1, 2, 3]: 
    def func(x): 
     return n*x 
    functions.append(func) 

# You would expect this to print [2, 4, 6] 
print(
    'calling a list of bad closures and output is: {}' 
    .format(str([function(2) for function in functions])) 
) 

Was genau ist hier passiert? Wenn die Funktion an die Liste angehängt wird, welche Werte hat sie? Kann jemand bitte diesen Code für mich verständlicher machen.

Antwort

1

Beachten Sie, dass Sie Funktionen zur Laufzeit mehr oder weniger wie lambdas in C++ erstellen können. Also im Grunde Sie über eine Liste iterieren, so dass n nehmen Werte 1,2 and 3

for n in [1, 2, 3]: 
    def func(x): 
     return n*x 

so durch jede Iteration eine Funktion namens func bauen, mit einem Wert annimmt und multipliziert es für n. Durch Anhängen an die Funktionsliste haben Sie diese Funktionen gespeichert, so dass Sie über die Liste iterieren können, um die Funktionen aufzurufen.

[function(2) for function in functions] 

Dadurch verhindern Sie jede der Funktionen mit dem Wert gespeichert rufen 2, würden Sie dies zur Ausgabe erwarten [2, 4, 6] ([1 * 2, 2 * 2, 3 * 2]), sondern es gibt [6, 6, 6] , WARUM ?, das ist, weil jede Funktion n für seine Berechnung benutzt, also tun sie nicht wirklich 1*x, 2*x and 3*x, aber wirklich n*x, und da x in der letzten Zeit an 3 binded, tun alle Funktionen 3*2, die 6 wird.

Spielen Sie mit der Python-Konsole herum, um es richtig zu überprüfen.

0

In der Sprache von C++ wird ein Zeiger auf die Funktion an die Liste angehängt. Nach der for Schleife enthält functions Zeiger auf drei verschiedene Funktionen (func(x) = n * x, func(x) = n * x und func(x) = n * x). Beachten Sie die Abhängigkeit von n. Wenn sich n ändert, ändert sich auch das Verhalten dieser Funktionen, und sie sind alle gleichwertig. Im zweiten Teil des Codes werden die Zeiger aus der Liste extrahiert und jede der drei Funktionen wird mit dem Argument 2 ausgewertet.

Hier ist ein weiteres Beispiel zu klären. Stellen wir uns folgendes vor:

>>> functions 
[<function func at 0x0239AA70>, <function func at 0x0239AAB0>, <function func at 0x0239AB30>] 
>>> g = functions[2] 
>>> g 
<function func at 0x0239AB30> 
>>> g(10) 
20 
>>> g(100) 
200 

Was wir in diesen ersten Zeilen sehen, ist, dass Funktionen Zeiger auf drei verschiedene Funktionen enthält. Die nächste Zeile extrahiert den dritten Zeiger aus der Liste (der sich auf func(x) = n * x bezieht) und weist ihn g zu. Effektiv haben wir mit diesem Aufruf eine Funktion g(x) = n * x definiert. Wir können nun g mit Argumenten auswerten.

Beachten Sie, dass, da alle Funktionen von n abhängen, Sie n ändern können, und das Verhalten würde sich ändern.

>>> n = 100 
>>> g(10) 
1000 
+0

Aber wäre das nicht yeild [2 4 6] statt [6 6 6] – RickMota

+0

Daniels Antwort ist richtig - er etwas gefangen habe ich nicht. Sie alle beziehen sich auf n, und da sich n am Ende auf einen Wert von 2 festgelegt hat, verhalten sich alle Funktionen genau gleich. – Christian

+0

Ich habe geändert, um die Abhängigkeit von n zu erwähnen, und verlasse die gelieferte Lösung, um die Verbindung zu Zeigern in C++ zu klären. – Christian