2010-10-19 11 views
38

¿Hay una manera más fácil de hacer esto en Python (2.7) ?: Nota: Esto no es nada sofisticado, como poner todas las variables locales en un diccionario. Solo los que especifico en una lista.Variables de Python como claves para dict

apple = 1 
banana = 'f' 
carrot = 3 
fruitdict = {} 

# I want to set the key equal to variable name, and value equal to variable value 
# is there a more Pythonic way to get {'apple': 1, 'banana': 'f', 'carrot': 3}? 

for x in [apple, banana, carrot]: 
    fruitdict[x] = x # (Won't work) 
+1

Pueden las variables se definirán en los dict? Como fruitdict = dict (apple = 1, banana = 2, carrot = 3)? –

+0

No, realmente, hay un montón de código para cada variable, por lo que sería ilegible. – ash

+0

Supongo que sabe que su código no hace lo que el comentario dice que hace. No puede retroceder de objetos a nombres a menos que encuentre lo que desea en un diccionario de espacios de nombres como locals(). Sin embargo, podría escribir una función que busque estas variables en el diccionario de espacios de nombres y le asigne los valores encontrados; ver la respuesta de jimbob. – Thomas

Respuesta

44
for i in ('apple', 'banana', 'carrot'): 
    fruitdict[i] = locals()[i] 
+6

una línea '' dict ([(i, locals() [i]) para i en ('apple', 'banana', 'carrot')]) '' – dinya

11

La función globals() devuelve un diccionario que contiene todas las variables globales.

>>> apple = 1 
>>> banana = 'f' 
>>> carrot = 3 
>>> globals() 
{'carrot': 3, 'apple': 1, '__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'banana': 'f'} 

También hay una función similar llamada locals().

Me doy cuenta de que esto probablemente no es exactamente lo que quiere, pero puede proporcionar una idea de cómo Python proporciona acceso a sus variables.

Editar: Parece que su problema puede ser mejor resuelto por el simple uso de un diccionario en el primer lugar:

fruitdict = {} 
fruitdict['apple'] = 1 
fruitdict['banana'] = 'f' 
fruitdict['carrot'] = 3 
+0

Disculpe, debo haber editado después de que estaba escribiendo su respuesta. Solo necesito las variables que especifico, no todas las locals() o globales() – ash

+0

@Jasie: agregué un ejemplo de simplemente usar un diccionario en primer lugar, en lugar de meterme con las variables. –

1

Si desea enlazar las ubicaciones de las variables mismas, hay esto:

>>> apple = 1 
>>> banana = 'f' 
>>> carrot = 3 
>>> fruitdict = {} 
>>> fruitdict['apple'] = lambda : apple 
>>> fruitdict['banana'] = lambda : banana 
>>> fruitdict['carrot'] = lambda : carrot 
>>> for k in fruitdict.keys(): 
...  print k, fruitdict[k]() 
... 
carrot 3 
apple 1 
banana f 
>>> apple = 7 
>>> for k in fruitdict.keys(): 
...  print k, fruitdict[k]() 
... 
carrot 3 
apple 7 
banana f 
+0

Gracias, pero los números eran asignaciones aleatorias (no necesitaban un rango()). – ash

4

A de una sola línea es: -

fruitdict = dict(zip(('apple','banana','carrot'), (1,'f', '3')) 
+0

Gracias, pero los números eran asignaciones aleatorias (no necesitaban un rango()). – ash

+0

Ahora hay dos listas – Dantalion

0

por qué no hacer lo contrario:

fruitdict = { 
     'apple':1, 
     'banana':'f', 
     'carrot':3, 
} 

locals().update(fruitdict) 

Actualización:

no utilizan el código anterior comprobar el comentario.

por cierto ¿por qué no marca los VARs que desea obtener no sé tal como esto:

# All the vars that i want to get are followed by _fruit 
apple_fruit = 1 
carrot_fruit = 'f' 

for var in locals(): 
    if var.endswith('fruit'): 
     you_dict.update({var:locals()[var]) 
+4

Actualizando 'locals() 'así es realmente malvado. –

+0

Como dice un amigo mío: "vudú oscuro" –

+0

estoy de acuerdo, pero mi comprensión de su pregunta es que él quiere obtener solo variables que son __fruit y legume__; que es básicamente imposible a menos que él pueda enseñarle a su programa a hacer la diferencia entre __fruit y legume__ y otras cosas, o tal vez solo lo complique, tal vez solo quiere "vars zanahoria, plátano, manzana" :) – mouad

0

Bueno, esto es un poco, umm ... no Pythonic ... fea ... hacker ...

He aquí un fragmento de código suponiendo que desea crear un diccionario de todas las variables locales que cree después de un puesto de control específica es tomada:

checkpoint = [ 'checkpoint' ] + locals().keys()[:] 
## Various local assigments here ... 
var_keys_since_checkpoint = set(locals().keys()) - set(checkpoint) 
new_vars = dict() 
for each in var_keys_since_checkpoint: 
    new_vars[each] = locals()[each] 

Tenga en cuenta que agregamos explícitamente la clave 'checkpoint' en nuestra captura del locals().keys(). También estoy tomando explícitamente una parte de eso, aunque no debería ser necesario en este caso, ya que la referencia debe aplanarse para agregarla al [lista de 'puntos de control']. Sin embargo, si estaba usando una variante de este código e intentó atajar los ['checkpoint'] + portion (because that key was already in locals() , for example) ... then, without the [:] slice you could end up with a reference to the locals(). Keys() `cuyos valores cambiarían a medida que agrega variables.

Offhand No puedo pensar en una forma de llamar a algo como new_vars.update() con una lista de teclas para agregar/actualizar. Entonces, el ciclo for es más portátil. Supongo que la comprensión de un diccionario podría usarse en versiones más recientes de Python. Sin embargo, eso parecería ser nada más que una ronda de golf de código.

0

Esta pregunta prácticamente ha sido respondida, pero yo sólo quería decir que era divertido que usted ha dicho

Esto no es algo de fantasía, como poner todas las variables locales en un diccionario .

Debido a que es en realidad "más elegante"

lo que quiere decir:

apple = 1 
banana = 'f' 
carrot = 3 
fruitdict = {} 

# I want to set the key equal to variable name, and value equal to variable value 
# is there a more Pythonic way to get {'apple': 1, 'banana': 'f', 'carrot': 3}? 

names= 'apple banana carrot'.split() # I'm just being lazy for this post 
items = globals()     # or locals() 

for name in names: 
    fruitdict[name] = items[name] 

Honestamente, lo que está haciendo es sólo copiar elementos de un diccionario a otro.

(Greg Hewgill prácticamente dio toda la respuesta, me lo acabo de completar)

... y como personas sugirieron, es probable que se debe poner estos en el diccionario, en primer lugar, pero voy a asumir que por alguna razón no puede

+0

así que supongo que no vi la publicación de jimbob ... prácticamente lo mismo, simplemente no llama a locales/globales más de una vez –

+0

No creo que llamar a Globales más de una vez sea más eficiente. –

+0

P. ej., si haces elementos = locales(); id (locals()) == id (elementos) obtendrías igualdad. O si hiciste cosas = locales(); b = 3; items ['b'] encontrará la nueva variable b, ya que en realidad no copió los dls locales a los ítems (que serían más lentos). Si ha hecho los elementos = locales(), copiar() puede haber una diferencia menor; pero, de nuevo, el paso de la copia es probablemente más lento que el acceso a la pequeña cantidad de elementos del dict local. –

-1
a = "something" 
randround = {} 
randround['A'] = "%s" % a 

Funcionó.

+0

Debería ser '{'a': 'algo'}' y obtendría '{'A': 'algo'}' ... está difícil de codificar la clave 'A' – DarkCygnus

0

Sobre la base de la respuesta por mouad, aquí está una manera más Pythonic para seleccionar las variables basadas en un prefijo:

# All the vars that I want to get start with fruit_ 
fruit_apple = 1 
fruit_carrot = 'f' 
rotten = 666 

prefix = 'fruit_' 
sourcedict = locals() 
fruitdict = { v[len(prefix):] : sourcedict[v] 
       for v in sourcedict 
       if v.startswith(prefix) } 
# fruitdict = {'carrot': 'f', 'apple': 1} 

incluso se puede poner esto en una función con prefijo y sourcedict como argumentos.

1

Aquí está en una línea, sin tener que volver a escribir ninguna de las variables o de sus valores:

fruitdict.update({k:v for k,v in locals().copy().iteritems() if k[:2] != '__' and k != 'fruitdict'}) 
Cuestiones relacionadas