2008-10-23 21 views
13

Tengo una lista de nombres de variables, como esto:Dada una lista de nombres de variables en Python, ¿cómo puedo crear un diccionario con los nombres de variables como claves (a los valores de las variables)?

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

(Originalmente preguntó cómo convertir una lista de variables Véase la respuesta de Greg Hewgill a continuación..)

¿Cómo se convierte a un diccionario donde las claves son los nombres de las variables (como cadenas) y los valores son los valores de las variables?

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

Ahora que estoy volver a hacer la pregunta, se me ocurrió:

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

Puede eso ser mejorados?

actualización, respondiendo a la pregunta (en un comentario) de por qué me gustaría hacer esto:

a menudo me encuentro con el operador% de cuerdas con un diccionario de nombres y valores para interpolar . A menudo, los nombres en la cadena son solo los nombres de las variables locales. Así que (con la respuesta más abajo) que pueda hacer algo como esto:

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

Dear %(name)s, 
...''' % dict((x, locals()[x]) for x in ['name', 'zip']) 
+0

Modding down. No veo ninguna situación razonable en la que quieras hacer eso, y no veo la manera de hacerlo sólido, y ciertamente no con la evaluación. ¿Qué sucede si el nombre de la lista de nombres oculta uno de los nombres de interés, etc. – ddaa

+0

Respuesta a la actualización en respuesta a mi comentario: el modismo de Python para hacer eso (que no apoyo, pero he visto usado), es "string% locals()" directamente. – ddaa

+1

Puede reemplazar 'dict ((x, locals() [...)' por solo 'vars()'. – jfs

Respuesta

14

Olvídese de filtrar locals()! El diccionario que le da a la cadena de formato tiene permitido contener claves no utilizadas:

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

y si están usando el método str.format() hazlo así: ''{name} {zip}'. format (** locals())' – krupan

4

Su lista original [foo, bar, baz] no contiene las variables nombres, que sólo contiene elementos que hacen referencia a los mismos valores como las variables usted enumeró Esto se debe a que puede tener dos nombres de variable diferentes que hacen referencia al mismo valor.

Por lo tanto, la lista por sí sola no contiene información sobre qué otros nombres hacen referencia a los objetos. El primer elemento de su matriz tiene el nombre foo pero también tiene el nombre a[0] (suponiendo que su matriz se llame a). Después de ejecutar el siguiente código, quux se refiere también a un mismo objeto:

quux = a[0] 

Actualización: Tienes razón que se puede utilizar eval() por eso, pero su uso es hacerlo en general. Python proporciona un miembro especial llamado __dict__ que contiene la tabla de símbolos para el módulo actual. Para que pueda:

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

tener que import __main__ cuando el código se encuentra en el módulo principal sin nombre es un capricho de Python.

3

Puede usar la lista o las comprensiones del generador para crear una lista de clave, tuplas de valor utilizadas para crear una instancia directa de un dict. La mejor manera es a continuación:

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

Además, si se sabe, por ejemplo, la existencia de las variables de la tabla de símbolos local que puede ahorrarse de la función eval peligrosa mirando la variable directamente de los locales:

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

Después de su actualización final, creo que la respuesta a continuación es realmente lo que desea.Si solo está utilizando esto para la expansión de cadenas con las cadenas que controla, simplemente pase locals() directamente a la expansión de cadenas y seleccionará los valores deseados

Sin embargo, estas cadenas podrían provenir alguna vez de una fuente externa (por ejemplo, archivos de traducción), de lo que es una buena idea para filtrar los locales()

+0

dado que puede haber claves no utilizadas en el diccionario, solo puede usar "..."% locals() sin filtrar – hop

+0

De acuerdo, "..." % locals() es mucho más Pythonic también, en que es una expresión común. – ephemient

+0

Lo hice funcionar usando dict ([(name, locals() [name]) para el nombre en list_of_variable_names]) – pheon

1

No es eficiente, pero sin invocar eval:

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

o

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

según lo que desee.

Cuestiones relacionadas