You are here: Partenza > Dive Into Python > Elaborare HTML > locals e globals | << >> | ||||
Dive Into PythonPython per programmatori esperti |
Python dispone di due funzioni built-in, locals e globals che forniscono un accesso basato sui dizionari alle variabili locali e globali.
Prima però, una parola sui namespace (ndt: spazio dei nomi). È un argomento noioso, ma importante, perciò fate attenzione. Python usa quelli che sono chiamati namespace per tenere traccia delle variabili. Un namespace è come un dizionario nel quale le chiavi sono i nomi delle variabili ed i valori del dizionario sono i valori di quelle variabili. Infatti, potete accedere ad un namespace come ad un dizionario Python, come vedremo fra un minuto.
Ad ogni particolare punto di un programma Python, ci sono alcuni namespace disponibili. Ogni funzione ha il suo namespace, chiamato namespace locale, il quale tiene traccia delle variabili della funzione, inclusi gli argomenti della funzione e le variabili definite localmente. Ogni modulo ha il suo proprio namespace, chiamato namespace globale, che tiene traccia delle variabili del modulo, incluse funzioni, classi, ogni altro modulo importato, variabili e costanti di livello modulo. E c'è anche il namespace built-in, accessibile da ogni modulo, che contiene le funzioni built-in e le eccezioni.
Quando una linea di codice chiede il valore della variabile x, Python ricerca quella variabile in tutti i namespace disponibili, nell'ordine:
Se Python non trova x in nessuno di questi namespace, si fermerà e solleverà un'eccezione NameError con il messaggio There is no variable named 'x', come avete visto nel Capitolo 2, ma senza sapere quanto lavoro facesse Python prima di darvi quell'errore.
Python 2.2 introdusse un subdolo ma importante cambiamento che modificò
l'ordine di ricerca dei namespace: gli scope nidificati. Nelle versioni di
Python precedenti al 2.2, quando vi riferite ad una variabile dentro ad una
funzione nidificata o una
funzione lambda, Python
ricercherà quella variabile
nel namespace corrente della funzione, e poi nel namespace del modulo.
Python 2.2 ricercherà la variabile nel namespace della funzione corrente,
poi nel namespace della funzione genitore, e poi nel
namespace del modulo.
Python 2.1 può lavorare in ogni modo;
predefinitamente, lavora come Python 2.0, ma potete
aggiugere la seguente linea di codice in cima al vostro modulo
per farlo funzionare come Python 2.2:
from __future__ import nested_scopes |
Come molte cose in Python, i namespace sono direttamente accessibili a run-time. Specificatamente, il namespace locale è accessibile dalla funzione built-in locals, e quello globale (livello modulo) è accessibile dalla funzione built-in globals.
>>> def foo(arg): ... x = 1 ... print locals() ... >>> foo(7) {'arg': 7, 'x': 1} >>> foo('bar') {'arg': 'bar', 'x': 1}
Ciò che locals fa per il namespace locale, globals lo fa per il namespace globale. globals è più eccitante quindi, perché il namespace di un modulo è più interessante. [9] Il namespace di un modulo non include solo le variabili e le costanti di livello modulo, include anche tutte le funzioni e le classi definite nel modulo. In più, include ogni cosa che è stata importata nel modulo.
Ricordate la differenza tra from module import e import module? Con import module, il modulo stesso è importato, ma mantiene il suo proprio namespace, visto che dovete usare il nome del modulo per accedere ad ogni sua funzione od attributo: modulo.funzione. Ma con from module import, state realmente importando funzioni ed attributi specifici da un altro modulo nel vostro namespace, perciò potete accedervi senza riferirvi direttamente al modulo da cui provengono. Con la funzione globals, potete vedere come ciò avvenga.
Aggiungete il seguente blocco di codice a BaseHTMLProcessor.py:
if __name__ == "__main__": for k, v in globals().items(): print k, "=", v
Non fatevi intimidire, ricordate che avete già visto tutto questo in precedenza. La funzione globals ritorna un dizionario, e stiamo iterando attraverso il dizionario usando il metodo items e l'assegnamento multi-variabile. L'unica cosa nuova qui è la funzione globals. |
Ora lanciare lo script dalla linea di comando darà il seguente output:
c:\docbook\dip\py>python BaseHTMLProcessor.py
SGMLParser = sgmllib.SGMLParser htmlentitydefs = <module 'htmlentitydefs' from 'C:\Python21\lib\htmlentitydefs.py'> BaseHTMLProcessor = __main__.BaseHTMLProcessor __name__ = __main__ [...snip...]
SGMLParser è stato importato da sgmllib, usando from module import. Questo significa che è stato importato direttamente nel namespace del nostro modulo, e lì lo troviamo. | |
Al contrario il modulo htmlentitydefs, è stato importato usando import. Questo significa che il modulo htmlentitydefs stesso si trova nel nostro namespace, ma la variabile entitydefs definita nel modulo htmlentitydefs invece no. | |
Questo modulo definisce un'unica classe, BaseHTMLProcessor. Notate che il valore qui è la classe stessa, non una specifica istanza della classe. | |
Ricordate il trucco if __name__? Quando lanciate un modulo (al contrario di importarlo da un altro modulo), l'attributo built-in __name__ ottiene un valore speciale, __main__. Dato che abbiamo lanciato questo modulo come uno script dalla linea di comando, __name__ diventa __main__, questo giustifica il nostro piccolo script di test a stampare la globals appena eseguita. |
Usando le funzioni locals e globals, potete ottenere il valore di variabili arbitrarie dinamicamente, rendendo disponibile il nome della variabile come una stringa. Questo rispecchia la funzionalità della funzione getattr, che vi permette di accedere a funzioni arbitrarie dinamicamente, rendendo disponibile il nome della funzione come stringa. |
C'è un'altra importante differenza fra locals e globals che dovreste imparare adesso, prima di pagarne le conseguenze. Vi colpirà ugualmente, ma almeno poi la ricorderete, imparandola.
def foo(arg): x = 1 print locals() locals()["x"] = 2 print "x=",x z = 7 print "z=",z foo(3) globals()["z"] = 8 print "z=",z
[9] Non è che io esca poi molto. ;-)
<< Introdurre BaseHTMLProcessor.py |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
Formattazione di stringhe basata su dizionario >> |