2010-02-23 10 views
20

Me resulta muy útil para poder crear nuevas variables en tiempo de ejecución y crear un diccionario de los resultados para su posterior procesamiento, es decir, escribir en un archivo:Python: El uso de vars() para asignar una cadena a una variable

myDict = {} 
for i in range (1,10): 
    temp = "variable"+str(i) 
    vars()[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc. 
    myDict[temp] = vars(temp) 

que crea la entrada del diccionario [resultado1: datos1] a la que puedo llamar con myDict [resultado1]. He estado usando vars() sin realmente entender lo que estoy haciendo. Lo tomo vars() devuelve un diccionario con las variables locales, y

vars() [x] = Y

crea una nueva entrada en el diccionario de [x: y] (?)?

Tengo un script donde paso en un diccionario preparado con {input1: data1, input2: data2}, y utilizo este método para recorrer todos los valores, almacenar todos los resultados y enviarlo a un archivo. Este bit de código está dentro de una función dentro de una clase, y está funcionando.

Mi fuente de confusión es que he leído varios mensajes sobre cómo locals() no debe ser ensuciado con, y cómo vars() es equivalente (?) A la población local() o globales() ..

Así que mi pregunta es (al menos) dos aspectos:

1. ¿qué hace exactamente vars(), o en particular, vars() [x] = y hacer,

2.Que el alcance de este diccionario es (lo que debo tener en cuenta cuando escribo programas más grandes

3.Si esta es una buena programación práctica.

¡Gracias de antemano!

Respuesta

32

La forma Pythonic para crear una secuencia de variables

Si desea una secuencia de variables, crear una secuencia. En lugar de tratar de crear las variables independientes como:

variable0 
variable1 
variable2 
variable3 

usted debe buscar en la creación de un list. Esto es similar a lo que está sugiriendo S. Lott (S. Lott por lo general tiene un buen consejo), pero los mapas más perfectamente en el bucle de for:.

sequence = [] 
for _ in xrange(10): 
    sequence.append(function_that_returns_data()) 

(Tenga en cuenta que descartamos la variable de bucle (_) Hemos simplemente tratar de conseguir 10 pases)

a continuación, los datos estarán disponibles como:.

sequence[0] 
sequence[1] 
sequence[2] 
sequence[3] 
[...] 
sequence[9] 

como un beneficio adicional, que puede hacer:

for datum in sequence: 
    process_data(datum) 

Al principio, puede contraerse para que su secuencia comience en 0. Puede pasar por varias contorsiones para que sus datos reales comiencen en 1, pero es más doloroso de lo que vale. Recomiendo simplemente acostumbrarme a tener listas basadas en cero. Todo está construido a su alrededor, y comienzan a sentirse naturales bastante rápido.

vars()() y los locales

Ahora, para responder a otra parte de su pregunta. vars() (o locals()) proporciona acceso de bajo nivel a las variables creadas por python. Por lo tanto, las siguientes dos líneas son equivalentes.

locals()['x'] = 4 
x = 4 

El alcance de vars()['x'] es exactamente el mismo que el alcance de x. Un problema con locals() (o vars()) es que le permitirá colocar cosas en el espacio de nombres que no puede salir del espacio de nombres por medios normales. Por lo tanto, puede hacer algo como esto: locals()[4] = 'An integer', pero no puede volver a salir sin utilizar locales nuevamente, porque el espacio de nombres local (como con todos los espacios de nombres de Python) solo está destinado a contener cadenas.

>>> x = 5 
>>> dir() 
['__builtins__', '__doc__', '__name__', 'x'] 
>>> locals()[4] = 'An integer' 
>>> dir() 
[4, '__builtins__', '__doc__', '__name__', 'x'] 
>>> x 
5 
>>> 4 
4 
>>> locals()[4] 
'An integer' 

Tenga en cuenta que 4 no devuelve lo mismo que locals() [4]. Esto puede conducir a algunos problemas inesperados y difíciles de solucionar. Esta es una razón para evitar el uso de locals().Otra es que, en general, es una gran complicación hacer las cosas que Python proporciona formas más simples y menos propensas a errores (como crear una secuencia de variables).

+2

Creo que 'vars() ['x'] = 4' y' x = 4' en realidad son equivalentes solo algunas veces. Si hace esto en una función, y no establece 'x' en otro lugar, y la función es optimizada por el compilador, entonces la búsqueda normal de' x' más adelante en la función (es decir, 'y = x + 2') ganó no funciona Creo que el compilador almacena en caché las variables que puede ver (posiblemente definidas en tiempo de compilación) y no tiene en cuenta este tipo de shenanigan. Si agrega una declaración ejecutiva a su función, entonces el compilador no intentará optimizar la función. –

+1

gracias por la respuesta, para el datum en secuencia: función (datum) parece muy útil. Aquí hay muchas cosas que aprendí, ¡gracias! – PPTim

+0

Para obtener más información sobre esa construcción, busque "iteradores de python" – jcdyer

2

Respondo el número 3: esta no es una buena práctica de programación. No veo exactamente lo que está intentando lograr, pero estoy seguro de que hay una forma más elegante de hacerlo sin usar locals() (que es lo mismo que vars() según help(vars) en el shell interactivo de Python).

5

De la ayuda de VARs,

VARs (...) VARs ([objeto]) -> diccionario

Without arguments, equivalent to locals(). 
With an argument, equivalent to object.__dict__. 

usted lo está utilizando, sin VARs, así que vamos a mirar a la ayuda para los locales()

gente (...) locals() -> diccionario

Update and return a dictionary containing the current scope's local 

variables.

Así que esto le responde las dos primeras preguntas. vars() devuelve un diccionario a las variables locales que está indexado por el nombre de la variable como una cadena. El alcance es local.

No estoy seguro acerca de la tercera pregunta, pero parece una especie de truco que no es una buena señal.Supongo que si tienes cuidado al usar esto solo en el alcance correcto, puedes hacerlo con él.

+0

i metí tanto en mi confusión me olvidé de pedir ayuda(). Gracias, – PPTim

6

Haga esto en su lugar. Es mas simple

myDict = {} 
for i in range (1,10): 
    temp = "variable"+str(i) 
    myDict[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc. 

Eso es todo lo que necesitas hacer.

Los resultados serán myDict['variable1'] través myDict['variable9']

Rara vez se necesita vars() o locals(). Solo deja de usarlos y usa variables ordinarias y diccionarios comunes. Trata de evitar cosas que no entiendes y apega a las cosas simples y obvias.

+0

Ahora que pienso acerca de por qué utilicé vars(), probablemente fue porque me sentí bien al poder llamar las variables desde IDLE cuando probé el código línea por línea. ¡Gracias por la respuesta! – PPTim

1

Usar vars/locales o globales de esta manera es (a) una práctica deficiente y (b) no funciona en todos los casos. Vea Dynamically set local variable para más detalles. En pocas palabras: solo use dicts, para eso están.

4

jcdyer explica los conceptos muy bien y Justin Peel indica claramente lo que vars() y locals() hacen. Pero un pequeño ejemplo siempre acelera la comprensión.

class Bull(object): 

    def __init__(self): 
     self.x = 1 
     self.y = "this" 

    def __repr__(self): 
     return "Bull()" 

    def test1(self): 
     z = 5 
     return vars() 

    def test2(self): 
     y = "that" 
     return vars(self) 

    def test3(self): 
     return locals() 

    def test4(self): 
     y = 1 
     return locals() 

if __name__ == "__main__": 
    b = Bull() 
    print b.test1() 
    print b.test2() 
    print b.test3() 
    print b.test4() 
    print vars(b).get("y") 

que se traduce en:

{'self': Bull(), 'z': 5} 
{'y': 'this', 'x': 1} 
{'self': Bull()} 
{'y': 1, 'self': Bull()} 
this 
Cuestiones relacionadas