Étant donné une liste de noms de variables en Python, comment puis-je créer un dictionnaire avec les noms de variables comme clés (pour les valeurs des variables)?

StackOverflow https://stackoverflow.com/questions/230896

  •  04-07-2019
  •  | 
  •  

Question

J'ai une liste de noms de variables, comme ceci:

['foo', 'bar', 'baz']

(À l'origine, j'avais demandé comment convertir une liste de variables. Voir la réponse de Greg Hewgill ci-dessous.)

Comment puis-je convertir cela en un dictionnaire où les clés sont les noms de variables (sous forme de chaînes) et les valeurs sont les valeurs des variables?

{'foo': foo, 'bar': bar, 'baz': baz}

Maintenant que je pose à nouveau la question, je suis arrivé avec:

d = {}
for name in list_of_variable_names:
    d[name] = eval(name)

Peut-on améliorer cela?

Mettre à jour en répondant à la question (dans un commentaire) de la raison pour laquelle je souhaite procéder ainsi:

Je me retrouve souvent à utiliser l'opérateur% pour les chaînes avec un dictionnaire de noms et de valeurs à interpoler. Souvent, les noms dans la chaîne ne sont que les noms de variables locales. Donc (avec la réponse ci-dessous), je peux faire quelque chose comme ceci:

message = '''Name: %(name)s
ZIP: %(zip)s

Dear %(name)s,
...''' % dict((x, locals()[x]) for x in ['name', 'zip'])
Était-ce utile?

La solution

Oubliez le filtrage des locals () ! Le dictionnaire que vous attribuez à la chaîne de mise en forme est autorisé à contenir des clés inutilisées:

>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> locals()
{'name': 'foo', 'zip': 123, ... 'unused': 'whoops!', ...}
>>> '%(name)s %(zip)i' % locals()
'foo 123'

Avec la nouvelle fonction de chaîne f dans Python 3.6, avec locals () n'est plus nécessaire:

>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> f'{zip: >5} {name.upper()}'
'  123 FOO'

Autres conseils

Votre liste d'origine [foo, bar, baz] ne contient pas la variable noms , elle contient uniquement des éléments qui font référence aux mêmes valeurs comme les variables que vous avez énumérées. En effet, vous pouvez avoir deux noms de variable différents faisant référence à la même valeur.

Ainsi, la liste en elle-même ne contient pas d’informations sur ce que les autres noms font référence aux objets. Le premier élément de votre tableau porte le nom toto , mais il porte également le nom a [0] (en supposant que votre tableau s'appelle a ). Après avoir exécuté le code suivant, quux fait également référence au même objet:

quux = a[0]

Mise à jour: Vous avez raison de dire que vous pouvez utiliser eval () pour cela, mais son utilisation est généralement déconseillée. Python fournit un membre spécial nommé __ dict __ qui contient la table des symboles pour le module actuel. Pour que vous puissiez:

import __main__
d = dict((x, __main__.__dict__[x]) for x in list_of_variable_names)

Devoir importer __main __ lorsque votre code est dans le module principal non nommé est une bizarrerie de Python.

Vous pouvez utiliser les compréhensions de liste ou de générateur pour construire une liste de nuplets de clés utilisés pour instancier directement un dict. La meilleure façon est ci-dessous:

dict((name, eval(name)) for name in list_of_variable_names)

De plus, si vous savez, par exemple, que les variables existent dans la table des symboles locale, vous pouvez vous sauver de l'évaluation dangereuse en regardant la variable directement à partir des adresses locales:

dict((name, locals()[name]) for name in list_of_variable_names)

Après votre dernière mise à jour, je pense que la réponse ci-dessous est vraiment ce que vous voulez. Si vous ne l'utilisez que pour développer des chaînes avec les chaînes que vous contrôlez, transmettez simplement locals () directement à l'extension et cela sélectionnera les valeurs souhaitées

Si, toutefois, ces chaînes peuvent provenir d'une source externe (fichiers de traduction, par exemple), il est préférable de filtrer les variables locales ()

Pas efficace, mais sans invoquer eval :

dict((k,v) for (k,v) in globals().iteritems() if k in list_of_variable_names)

ou

dict((k,v) for (k,v) in vars().iteritems() if k in list_of_variable_names)

en fonction de ce que vous voulez.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top