2013-06-21 4 views
6

Sto leggendo questo article sul decoratore.scope variabile python in funzioni nidificate

A Passo 8, v'è una funzione definita come:

def outer(): 
    x = 1 
    def inner(): 
     print x # 1 
    return inner 

e se corriamo facendo:

>>> foo = outer() 
>>> foo.func_closure # doctest: +ELLIPSIS 

non stampa x. Secondo la spiegazione:

Tutto funziona in base alle regole di scoping di Python - x è una variabile locale nella nostra funzione esterna. Quando stampe interne x al punto # 1 Python cerca una variabile locale all'interno e non la trova appare nell'oscilloscopio che è la funzione esterna, trovandola lì.

Ma per quanto riguarda le cose dal punto di vista della durata variabile? La nostra variabile x è locale alla funzione esterna, il che significa che esiste solo mentre la funzione esterna è in esecuzione. Non siamo in grado di chiamare interno fino al dopo il ritorno di esterno così secondo il nostro modello di come Python funziona, x non dovrebbe esistere più dal momento in cui chiamiamo interno e forse dovrebbe verificarsi un errore di runtime di qualche tipo.

Tuttavia, non capisco cosa significhi il secondo paragrafo.

Capisco inner() ottiene il valore di x ma perché non stampa x out?

grazie

UPDATE:

Grazie a tutti per le risposte. Ora capisco la ragione. il "ritorno interno" è solo un puntatore per interno(), ma non viene eseguito, è per questo che interna() non stampa x quanto non si chiama affatto

risposta

2

Non stai chiamando inner. Hai chiamato outer, che restituisce inner, ma senza chiamarlo. Se si desidera chiamare inner, fare foo() (dal momento che si assegna il risultato di outer() al nome foo).

Il paragrafo che hai citato è in qualche modo tangenziale a questo problema. Dici di aver già capito perché lo inner ottiene il valore di x, che è quello che sta spiegando quel paragrafo. In sostanza, se una variabile locale viene utilizzata in una funzione nidificata e tale funzione nidificata viene restituita, il valore della variabile viene archiviato insieme alla funzione restituita, anche se l'ambito in cui tale variabile è stata definita non più attivo. Normalmente x scompare dopo lo outer terminato, perché x è solo locale a outer. Ma outer restituisce inner, che necessita ancora dell'accesso a x.Pertanto, x viene inserito in quella che viene chiamata chiusura, quindi è possibile accedervi in ​​seguito entro il inner.

+0

OP chiede anche il motivo per cui 'x' esiste ancora – jamylak

+0

@jamylak: Non è chiaro per me se egli è o non è. Dice che non capisce quel paragrafo citato, ma dice anche di capire come 'inner' ha accesso a' x'. – BrenBarn

+0

in entrambi i casi hai chiarito ora – jamylak

7

Capisco inner() ottiene il valore di x ma perché non stampa x out?

Non stampa nulla perché non hai ancora chiamato la funzione interna.

>>> def outer(): 
     x = 1 
     def inner(): 
       print x # 1 
     return inner 
...  
>>> func = outer() 
>>> func    
<function inner at 0xb61e280c> 
>>> func() 
1 

Questo è chiamato un closure, cioè anche se la funzione esterno non è in pila (terminato l'esecuzione) più ma ancora la funzione interna che è stato restituito dal ricorda suo stato. (Valore di x)

>>> def outer(): 
      x = 1 
      y = 2 
      def inner(): 
        z=3 
        print x 
      return inner 
...  
>>> func = outer() 
>>> func.func_code.co_freevars #returns the variables that were used in closure 
('x',) 

Dal source code su come Python decide che è una chiusura o no:

459 if len(code.co_freevars) == 0: 
    460  closure = NULL 
    461 else: 
    462  len(closure) == len(code.co_freevars) 

In py3.x è possibile al quindi modificare il valore di x usando l'istruzione nonlocal all'interno della funzione interna.

>>> def outer(): 
     x = 1 
     def inner(): 
      nonlocal x 
      x += 1 
      print (x) 
     return inner 
...  
>>> func = outer() 
>>> func() 
2 
>>> func() 
3 
>>> func() 
4 
+2

+1 per l'istruzione '' nonlocal'' – Tregoreg