2011-07-27 12 views
15

Actualmente estoy aprendiendo Python, y tengo que trabajar en un proyecto de Python 2.7.accediendo a los vars del "módulo de alcance"

El acceso a las variables de "módulo de alcance" en las funciones del módulo en sí me resulta un poco confuso, y no pude encontrar una manera satisfactoria.

Mis intentos hasta ahora:

Way 1:

my_module.py

my_global_var = None 

def my_func(): 
    global my_global_var 
    my_global_var = 'something_else' 

Aquí creo que confusos y VARs locales "ámbito de módulo" pueden ser bastante fácil.

manera 2:

my_module.py

import my_module 

my_global_var = None 

def my_func(): 
    my_module.my_global_var = 'something_else' 

En este caso, el nombre de "mi_módulo" no se podía cambiar tan fácilmente como "modo 1" cuando sea necesario. Además, importar un módulo en sí mismo suena bastante extraño.

¿Qué recomendarías? ¿O sugerirías algo más? Gracias.

+1

No utilice 'Camino 2', usar' 1' Camino. El alcance y alcance de Python son interesantes. El intérprete siempre buscará un nombre del alcance más interno hacia afuera cuando lea el valor de un nombre. Cuando asigna un valor a un nombre, lo hace en el alcance actual.Esto significa que si asigna 'my_global_var' sin la palabra clave' global', su módulo tendrá dos 'my_global_var' diferentes desde el punto de la asignación de ámbito anidado y más allá en el ámbito anidado. La declaración global simplemente le está diciendo al intérprete que asigne valores al ámbito 'global' para el nombre' my_global_var'. – Matt

Respuesta

19

Probablemente desee leer en Python's namespaces. Vía 1 es correcta, pero suele ser innecesario, nunca use 2. Un enfoque más sencillo es usar un diccionario (o clase o algún otro objeto):

my_globals = {'var': None} 

def my_func(): 
    my_globals['var'] = 'something else' 

las asignaciones siempre van al alcance interno y de alcance interno es siempre buscado primero, por lo tanto, la necesidad de la palabra clave global. En este caso, no está asignando un nombre, por lo que es innecesario.

+3

Ah. Por lo tanto, los valores dict se pueden modificar en el alcance de la función, pero no en los valores de cadena sin formato. Python parece bastante contra-intuitivo aquí. De todos modos, esto funciona y se adapta exactamente a mi necesidad. gracias –

+0

Las asignaciones siempre entran en el ámbito más interno y siempre se buscan primero, por lo tanto, la necesidad de la palabra clave 'global'. En este caso, no está asignando un nombre, por lo que es innecesario (Python buscará el alcance más interno y no encontrará que 'my_globals' llegue al alcance del nivel de módulo. – zeekay

+0

Gracias por las explicaciones detalladas sobre este comportamiento. Lo entiendo mejor. –

3

La forma 1 es la forma correcta cuando absolutamente debe volver a vincular una variable global. Sin embargo, debe preguntarse por qué está modificando un global y si hay algo mejor que pueda hacer (como encapsular el comportamiento en una clase).

Se debe evitar importar un módulo en sí mismo ya que es propenso a errores. Si el módulo también es una secuencia de comandos, a veces deberá importar __main__, o si el módulo es parte de un paquete, tal vez debería importar foo.my_module. En resumen, no hagas eso.

1

Evite establecer globales. Puede crear nuevos espacios de nombres con clases con bastante facilidad, así que use variables de clase si es necesario.

Para cualquier cosa grave necesita un diseño adecuado con clases de todos modos.

+1

Gracias por su respuesta. Me gustaría crear un singleton, y la forma recomendada parece simplemente crear un módulo (ver http://stackoverflow.com/questions/31875/is-there-a-simple-elegant-way-to-define-singletons- in-python), así que preferiría evitar una clase en este caso particular. –

+0

@FrostyZ - Aconsejo no usar el módulo como singleton, aunque solo sea por la dificultad de las pruebas unitarias. Consulte

+0

Incluso para las pruebas, algunos singleton parecen aceptables (por ejemplo, un registrador). Consulte http://googletesting.blogspot.com/2008/08/root-cause-of-singletons.html –

3

Importar un módulo dentro de sí mismo puede tener efectos secundarios no deseados (como evaluar declaraciones más de una vez). Sugeriría usar "Forma 1" y una herramienta como pylint para ayudar a verificar su código y aplicar prácticas comunes.

pylint se puede encontrar en: http://www.logilab.org/project/pylint

Cuestiones relacionadas