Python: charger des variables dans un dict dans un espace de noms
Je veux utiliser un tas de variables locales définies dans une fonction, en dehors de la fonction. Donc, je passe x=locals()
dans la valeur de retour.
Comment puis-je charger toutes les variables définies dans ce dictionnaire dans l'espace de noms en dehors de la fonction, de sorte qu'au lieu d'accéder à la valeur en utilisant x['variable']
, je pourrais simplement utiliser variable
.
6 réponses
Considérons l'alternative Bunch
:
class Bunch(object):
def __init__(self, adict):
self.__dict__.update(adict)
Donc, si vous avez un dictionnaire d
et que vous voulez accéder (lire) à ses valeurs avec la syntaxe x.foo
au lieu du maladroit d['foo']
, faites simplement
x = Bunch(d)
Cela fonctionne à la fois à l'intérieur et à l'extérieur des fonctions-et c'est énormément plus propre et plus sûr que d'injecter d
dans globals()
! Rappelez-vous la dernière ligne du Zen de Python...:
>>> import this
The Zen of Python, by Tim Peters
...
Namespaces are one honking great idea -- let's do more of those!
C'est un cas parfaitement valide pour importer des variables dans un espace local dans un autre espace local aussi longtemps que on est conscient de ce qu'il/elle fait. J'ai vu plusieurs fois utilisé de façons utiles. Juste besoin de faire attention à ne pas polluer l'espace global commun.
Vous pouvez faire ce qui suit:
adict = { 'x' : 'I am x', 'y' : ' I am y' }
locals().update(adict)
blah(x)
blah(y)
L'importation de variables dans un espace de noms local est un problème valide et souvent utilisé dans les frameworks de modèles.
Renvoie toutes les variables locales d'une fonction:
return locals()
Puis importer comme suit:
r = fce()
for key in r.keys():
exec(key + " = r['" + key + "']")
, Plutôt que de créer votre propre objet, vous pouvez utiliser argparse.Namespace
:
from argparse import Namespace
ns = Namespace(**mydict)
Pour faire l'inverse:
mydict = vars(ns)
Il y a toujours cette option, Je ne sais pas que c'est la meilleure méthode, mais ça marche vraiment. En supposant type (x) = dict
for key, val in x.items(): # unpack the keys from the dictionary to individual variables
exec (key + '=val')
Utilisé l'extrait suivant (PY2) pour créer un espace de noms récursif à partir de mes configurations dict (yaml):
class NameSpace(object):
def __setattr__(self, key, value):
raise AttributeError('Please don\'t modify config dict')
def dump_to_namespace(ns, d):
for k, v in d.iteritems():
if isinstance(v, dict):
leaf_ns = NameSpace()
ns.__dict__[k] = leaf_ns
dump_to_namespace(leaf_ns, v)
else:
ns.__dict__[k] = v
config = NameSpace()
dump_to_namespace(config, config_dict)