Qual è la differenza tra globals(), locals()e vars()? Cosa ritornano? Gli aggiornamenti ai risultati sono utili?
Qual è la differenza tra globals(), locals()e vars()? Cosa ritornano? Gli aggiornamenti ai risultati sono utili?
Risposte:
Ognuno di questi restituisce un dizionario:
globals() restituisce sempre il dizionario dello spazio dei nomi del modulolocals() restituisce sempre un dizionario dello spazio dei nomi correntevars()restituisce un dizionario dello spazio dei nomi corrente (se chiamato senza argomento) o il dizionario dell'argomento.localse varspotrebbe usare qualche spiegazione in più. Se locals()viene chiamato all'interno di una funzione, aggiorna un dict con i valori dello spazio dei nomi delle variabili locali correnti (più eventuali variabili di chiusura) a partire da quel momento e lo restituisce. Più chiamate a locals()nello stesso frame dello stack restituiscono ogni volta lo stesso dict: è collegato all'oggetto frame dello stack come suo f_localsattributo. I contenuti del dict vengono aggiornati su ogni locals()chiamata e ogni f_localsaccesso agli attributi, ma solo su tali chiamate o accessi agli attributi. Non si aggiorna automaticamente quando le variabili sono assegnate e l'assegnazione delle voci nel dict non assegnerà le variabili locali corrispondenti:
import inspect
def f():
x = 1
l = locals()
print(l)
locals()
print(l)
x = 2
print(x, l['x'])
l['x'] = 3
print(x, l['x'])
inspect.currentframe().f_locals
print(x, l['x'])
f()
ci da:
{'x': 1}
{'x': 1, 'l': {...}}
2 1
2 3
2 2
Il primo print(l)mostra solo una 'x'voce, perché l'assegnazione lavviene dopo la locals()chiamata. Il secondo print(l), dopo aver richiamato di locals()nuovo, mostra una lvoce, anche se non abbiamo salvato il valore di ritorno. La terza e la quarta prints mostrano che l'assegnazione delle variabili non si aggiorna le viceversa, ma dopo l'accesso f_locals, le variabili locali vengono locals()nuovamente copiate .
Due note:
exec "pass"linea nella funzione. In questo modo la funzione passa a una modalità di esecuzione più vecchia e più lenta che utilizza il locals()comando come rappresentazione canonica delle variabili locali.Se locals()viene chiamato al di fuori di una funzione, restituisce il dizionario effettivo che è lo spazio dei nomi corrente. Ulteriori modifiche allo spazio dei nomi si riflettono nel dizionario e le modifiche al dizionario si riflettono nello spazio dei nomi:
class Test(object):
a = 'one'
b = 'two'
huh = locals()
c = 'three'
huh['d'] = 'four'
print huh
ci da:
{
'a': 'one',
'b': 'two',
'c': 'three',
'd': 'four',
'huh': {...},
'__module__': '__main__',
}
Finora, tutto ciò di cui ho parlato locals()è vero anche per vars()... ecco la differenza: vars()accetta un singolo oggetto come argomento, e se gli dai un oggetto restituisce l' __dict__oggetto. Per un oggetto tipico, __dict__è dove è archiviata la maggior parte dei suoi dati di attributo. Ciò include variabili di classe e moduli globali:
class Test(object):
a = 'one'
b = 'two'
def frobber(self):
print self.c
t = Test()
huh = vars(t)
huh['c'] = 'three'
t.frobber()
che ci dà:
three
Si noti che una funzione __dict__è il suo spazio dei nomi degli attributi, non le variabili locali. Non avrebbe senso che una funzione __dict__memorizzi le variabili locali, poiché la ricorsione e il multithreading significano che possono esserci più chiamate contemporaneamente a una funzione, ognuna con i propri locali:
def f(outer):
if outer:
f(False)
print('Outer call locals:', locals())
print('f.__dict__:', f.__dict__)
else:
print('Inner call locals:', locals())
print('f.__dict__:', f.__dict__)
f.x = 3
f(True)
che ci dà:
Inner call locals: {'outer': False}
f.__dict__: {'x': 3}
Outer call locals: {'outer': True}
f.__dict__: {'x': 3}
Qui, si fchiama ricorsivamente, quindi le chiamate interne ed esterne si sovrappongono. Ognuno vede le proprie variabili locali quando chiama locals(), ma entrambe le chiamate vedono lo stesso f.__dict__e f.__dict__non contiene variabili locali.
vars()o locals()dizionario chiamato all'interno di una funzione se lo usi eval(). Ad esempio: def test(): huh = locals(); huh['d'] = 4; print eval('d')stampa 4 quando test()viene eseguito!
dict(restituito da locals()) sembra riflettersi nello spazio dei nomi locale e le modifiche allo spazio dei nomi locale si riflettono nel dict(nel mio pitone). L'unica cosa è che le specifiche non garantiscono questo comportamento.
import thise in googlesite:docs.python.org namespace