2016-04-06 24 views
5

Ho un back-ground di C++ e cerco di imparare un po 'di python.Chiusure in pitone con chiusura tardiva

Whist Capisco le funzioni virtuali per C++, sfortunatamente non capisco cosa si intenda per associazione tardiva di chiusure in python.

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

Copy-Paste da un 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])) 
) 

Che cosa esattamente sta succedendo qui? Quando la funzione viene aggiunta all'elenco, quali valori ha? Qualcuno può per favore semplificare questo codice per me capire.

risposta

1

Si noti che è possibile creare funzioni in fase di esecuzione, più o meno come lambdas in C++. Quindi, in pratica si effettua l'iterazione un elenco, rendendo n valori tengono 1,2 and 3

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

così, per ogni iterazione si sta costruendo una funzione denominata func, con prende un valore e lo moltiplica per n. Aggiungendolo alla lista delle funzioni, queste funzioni verranno memorizzate, quindi puoi scorrere l'elenco per chiamare le funzioni.

[function(2) for function in functions] 

In questo modo si chiama ciascuna delle funzioni memorizzate con il valore 2, ci si aspetterebbe per emettere [2, 4, 6] ([1 * 2, 2 * 2, 3 * 2]), ma invece restituisce [6, 6, 6] , perché ?, questo è siccome ogni funzione utilizzo n per il suo calcolo, in modo che non sono realmente facendo 1*x, 2*x and 3*x ma in realtà n*x e dal momento che x è rilegato in ultima volta per 3 tutte le funzioni stanno facendo 3*2 wich diventa 6.

Gioca con la console python per controllarlo correttamente.

0

Nella lingua del C++, un puntatore alla funzione è ciò che viene aggiunto all'elenco. Dopo il ciclo for, functions contiene i puntatori a tre diverse funzioni (func(x) = n * x, func(x) = n * x e func(x) = n * x). Si noti la dipendenza da n. Come n cambia, così sarà il comportamento di queste funzioni, e sono tutte equivalenti.

Nella seconda parte del codice, i puntatori vengono estratti dall'elenco e ciascuna delle tre funzioni viene valutata con un argomento di 2.

Ecco un ulteriore esempio da chiarire. Immaginate facciamo questo:

>>> 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 

Quello che stiamo vedendo in quanto prime righe è che le funzioni contiene puntatori a tre funzioni diverse. La riga successiva estrae il terzo puntatore dall'elenco (che si riferisce a func(x) = n * x) e lo assegna a g. In effetti, abbiamo definito una funzione g(x) = n * x con questa chiamata. Ora possiamo valutare g con argomenti.

Nota che, poiché tutte le funzioni dipendono n, si potrebbe cambiare n, e il comportamento potrebbe cambiare.

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

Ma sarebbe questo non yeild [2 4 6] invece di [6 6 6] – RickMota

+0

risposta di Daniel è corretta - ha catturato qualcosa che io non ho. Si riferiscono tutti a n, e poiché n si è stabilizzato al valore 2 alla fine, tutte le funzioni si comporteranno nello stesso identico modo. – Christian

+0

Ho modificato per menzionare la dipendenza da n e sto lasciando la soluzione pubblicata per chiarire la connessione ai puntatori in C++. – Christian