peut-on mettre à jour l'un de ceux-ci en python 3 et faire fonctionner le script?
Charlie Parker
Réponses:
172
Chacun de ceux-ci renvoie un dictionnaire:
globals() renvoie toujours le dictionnaire de l' espace de noms du module
locals() renvoie toujours un dictionnaire de l' espace de noms courant
vars()renvoie soit un dictionnaire de l'espace de noms courant (s'il est appelé sans argument) soit le dictionnaire de l'argument.
localset varspourrait utiliser quelques explications supplémentaires. Si locals()est appelé dans une fonction, il met à jour un dict avec les valeurs de l'espace de nom de la variable locale actuelle (plus toutes les variables de fermeture) à partir de ce moment et le renvoie. Plusieurs appels à locals()dans le même cadre de pile renvoient le même dict à chaque fois - il est attaché à l'objet de cadre de pile en tant f_localsqu'attribut. Le contenu du dict est mis à jour à chaque locals()appel et à chaque f_localsaccès d'attribut, mais uniquement sur de tels appels ou accès d'attribut. Il ne se met pas à jour automatiquement lorsque des variables sont affectées et l'affectation d'entrées dans le dict n'affectera pas les variables locales correspondantes:
import inspect
def f():
x =1
l = locals()print(l)
locals()print(l)
x =2print(x, l['x'])
l['x']=3print(x, l['x'])
inspect.currentframe().f_locals
print(x, l['x'])
f()
nous donne:
{'x':1}{'x':1,'l':{...}}212322
Le premier print(l)n'affiche qu'une 'x'entrée, car l'affectation à lse produit après l' locals()appel. Le second print(l), après avoir locals()rappelé, affiche une lentrée, même si nous n'avons pas enregistré la valeur de retour. Les troisième et quatrième prints montrent que l'affectation de variables ne se met pas à jour let vice versa, mais après que nous y accédons f_locals, les variables locales sont à locals()nouveau copiées .
Deux notes:
Ce comportement est spécifique à CPython - d'autres Pythons peuvent autoriser les mises à jour à revenir automatiquement à l'espace de noms local.
Dans CPython 2.x, il est possible de faire ce travail en mettant une exec "pass"ligne dans la fonction. Cela fait passer la fonction à un mode d'exécution plus ancien et plus lent qui utilise le locals()dict comme représentation canonique des variables locales.
Si locals()est appelé en dehors d' une fonction, il renvoie le dictionnaire réel qui est l'espace de noms actuel. D'autres modifications apportées à l'espace de noms sont reflétées dans le dictionnaire et les modifications apportées au dictionnaire sont reflétées dans l'espace de noms:
classTest(object):
a ='one'
b ='two'
huh = locals()
c ='three'
huh['d']='four'print huh
Jusqu'à présent, tout ce que j'ai dit locals()est également vrai pour vars()... voici la différence: vars()accepte un seul objet comme argument, et si vous lui donnez un objet, il renvoie le __dict__de cet objet. Pour un objet typique, __dict__c'est là que la plupart de ses données d'attributs sont stockées. Cela inclut les variables de classe et les globaux de module:
classTest(object):
a ='one'
b ='two'def frobber(self):print self.c
t =Test()
huh = vars(t)
huh['c']='three'
t.frobber()
ce qui nous donne:
three
Notez qu'une fonction __dict__est son espace de noms d'attribut, pas des variables locales. Cela n'aurait aucun sens pour une fonction de __dict__stocker des variables locales, car la récursivité et le multithreading signifient qu'il peut y avoir plusieurs appels à une fonction en même temps, chacun avec ses propres locals:
Ici, fs'appelle lui-même récursivement, de sorte que les appels internes et externes se chevauchent. Chacun voit ses propres variables locales lorsqu'il appelle locals(), mais les deux appels voient la même chose f.__dict__et f.__dict__ne contiennent aucune variable locale.
La partie "et toutes les affectations au dictionnaire ne sont pas reflétées dans l'espace de noms local réel" pourrait être rédigée un peu à définir .
Sven Marnach
Curieusement, vous pouvez accéder aux variables ajoutées à un dictionnaire vars()ou locals()appelé dans une fonction si vous utilisez eval(). EG: def test(): huh = locals(); huh['d'] = 4; print eval('d')imprime 4 quand test()est exécuté!
Mark Mikofski
1
En fait, l'affectation au dict(retourné par locals()) se trouve être reflétée dans l'espace de noms local et les modifications apportées à l'espace de noms local se trouvent être reflétées dans le dict(dans mon python). La seule chose est que la spécification ne garantit pas ce comportement.
skyking
L' utilisation de la portée des noms de termes me semble plus facile que l' espace de noms .
surexchange
1
@overexchange: import thiset dans googlesite:docs.python.org namespace
Réponses:
Chacun de ceux-ci renvoie un dictionnaire:
globals()
renvoie toujours le dictionnaire de l' espace de noms du modulelocals()
renvoie toujours un dictionnaire de l' espace de noms courantvars()
renvoie soit un dictionnaire de l'espace de noms courant (s'il est appelé sans argument) soit le dictionnaire de l'argument.locals
etvars
pourrait utiliser quelques explications supplémentaires. Silocals()
est appelé dans une fonction, il met à jour un dict avec les valeurs de l'espace de nom de la variable locale actuelle (plus toutes les variables de fermeture) à partir de ce moment et le renvoie. Plusieurs appels àlocals()
dans le même cadre de pile renvoient le même dict à chaque fois - il est attaché à l'objet de cadre de pile en tantf_locals
qu'attribut. Le contenu du dict est mis à jour à chaquelocals()
appel et à chaquef_locals
accès d'attribut, mais uniquement sur de tels appels ou accès d'attribut. Il ne se met pas à jour automatiquement lorsque des variables sont affectées et l'affectation d'entrées dans le dict n'affectera pas les variables locales correspondantes:nous donne:
Le premier
print(l)
n'affiche qu'une'x'
entrée, car l'affectation àl
se produit après l'locals()
appel. Le secondprint(l)
, après avoirlocals()
rappelé, affiche unel
entrée, même si nous n'avons pas enregistré la valeur de retour. Les troisième et quatrièmeprint
s montrent que l'affectation de variables ne se met pas à jourl
et vice versa, mais après que nous y accédonsf_locals
, les variables locales sont àlocals()
nouveau copiées .Deux notes:
exec "pass"
ligne dans la fonction. Cela fait passer la fonction à un mode d'exécution plus ancien et plus lent qui utilise lelocals()
dict comme représentation canonique des variables locales.Si
locals()
est appelé en dehors d' une fonction, il renvoie le dictionnaire réel qui est l'espace de noms actuel. D'autres modifications apportées à l'espace de noms sont reflétées dans le dictionnaire et les modifications apportées au dictionnaire sont reflétées dans l'espace de noms:nous donne:
Jusqu'à présent, tout ce que j'ai dit
locals()
est également vrai pourvars()
... voici la différence:vars()
accepte un seul objet comme argument, et si vous lui donnez un objet, il renvoie le__dict__
de cet objet. Pour un objet typique,__dict__
c'est là que la plupart de ses données d'attributs sont stockées. Cela inclut les variables de classe et les globaux de module:ce qui nous donne:
Notez qu'une fonction
__dict__
est son espace de noms d'attribut, pas des variables locales. Cela n'aurait aucun sens pour une fonction de__dict__
stocker des variables locales, car la récursivité et le multithreading signifient qu'il peut y avoir plusieurs appels à une fonction en même temps, chacun avec ses propres locals:ce qui nous donne:
Ici,
f
s'appelle lui-même récursivement, de sorte que les appels internes et externes se chevauchent. Chacun voit ses propres variables locales lorsqu'il appellelocals()
, mais les deux appels voient la même chosef.__dict__
etf.__dict__
ne contiennent aucune variable locale.la source
vars()
oulocals()
appelé dans une fonction si vous utilisezeval()
. EG:def test(): huh = locals(); huh['d'] = 4; print eval('d')
imprime 4 quandtest()
est exécuté!dict
(retourné parlocals()
) se trouve être reflétée dans l'espace de noms local et les modifications apportées à l'espace de noms local se trouvent être reflétées dans ledict
(dans mon python). La seule chose est que la spécification ne garantit pas ce comportement.import this
et dans googlesite:docs.python.org namespace