2012-05-14 12 views
176

Sé que debería evitar el uso de variables globales en primer lugar debido a una confusión como esta, pero si tuviera que usarlos, ¿es la siguiente una forma válida de usarlos? (Estoy tratando de llamar la copia global de una variable creada en una función separada.)¿Variables globales de la función Python?

x = somevalue 

def func_A(): 
    global x 
    # Do things to x 
    return x 

def func_B(): 
    x=func_A() 
    # Do things 
    return x 

func_A() 
func_B() 

¿El x que la segunda función utiliza el mismo valor de la copia mundial de x que func_a usos y modifica? Al llamar a las funciones después de la definición, ¿importa el orden?

+0

tenga cuidado también de no asumir solo porque tiene una variable asignada en su función que python tratará las referencias antes de la asignación como tal. Hasta la primera asignación, si usó x, no sería la global, ni la local. Obtendrá la infame excepción UnboundLocalError en su cara :) – osirisgothra

Respuesta

267

Si simplemente desea acceder a una variable global, simplemente use su nombre. Sin embargo, para cambie el valor que necesita para utilizar la palabra clave global.

E.g.

global someVar 
someVar = 55 

Esto cambiaría el valor de la variable global a 55. De lo contrario, asignaría 55 a una variable local.

El orden de los listados de definición de función no importa (suponiendo que no se refieran entre sí de alguna manera), el orden en que se llaman sí lo hace.

+2

En el código que di, es func_B haciendo cosas (1) a la copia global de x (como se obtiene de func_A), (2) a una variable local x con el mismo valor del resultado de func_A, o (3) a una variable local x sin valor y (a los ojos del compilador) sin relación con "algún valor" o la x en func_A? –

+0

'x' en' func_B' es una variable local que obtiene su valor del valor de retorno de la llamada a 'func_A' - así que supongo que eso sería su (2) – Levon

+0

ok, digamos que x era una secuencia aleatoria de algún tipo generado por func_A (es decir, que func_A producía una x diferente cada vez que se ejecutaba). ¿Si ejecutamos el programa como está escrito hacemos que func_b modifique una x diferente a la que se produjo originalmente cuando func_a se llamó? Si es así, ¿cómo puedo solucionarlo? –

0

Debe utilizar la declaración global cuando desee modificar el valor asignado a una variable global.

No lo necesita para leer desde una variable global. Tenga en cuenta que llamar a un método en un objeto (incluso si altera los datos dentro de ese objeto) no altera el valor de la variable que contiene ese objeto (magia reflectante ausente).

+2

Esta redacción es desafortunada. En Python, el valor asignado a una variable es una referencia, por lo que es técnicamente correcto (y no tengo ninguna duda de que lo dijo), pero muchos lectores pueden interpretar "alterar el valor" como "mutar el objeto", que no es el caso - 'xs.append (xs.pop (0))' funciona bien sin 'global xs'. – delnan

+0

@delnan Mi respuesta está cuidadosamente redactada, pero lo aclararé. – Marcin

12

Como han señalado otros, debe declarar una variable global en una función cuando desee que esa función pueda modificar la variable global. Si solo desea acceder a él, entonces no necesita global.

entrar en un poco más de detalle sobre eso, lo que "modificar" significa es esto: si quieres re-unen el nombre global para que apunte a un objeto diferente, el nombre debe ser declarada global en el función.

Muchas operaciones que modifican (mutan) un objeto No volver a unir el nombre global para apuntar a un objeto diferente, y por lo que son todas válidas sin declarar el nombre global en la función.

d = {} 
l = [] 
o = type("object", (object,), {})() 

def valid():  # these are all valid without declaring any names global! 
    d[0] = 1  # changes what's in d, but d still points to the same object 
    d[0] += 1  # ditto 
    d.clear()  # ditto! d is now empty but it`s still the same object! 
    l.append(0) # l is still the same list but has an additional member 
    o.test = 1 # creating new attribute on o, but o is still the same object 
65

dentro de un ámbito de Python, cualquier asignación a una variable no se ha declarado dentro de ese ámbito crea una nueva variable local menos esa variable se declaró anteriormente en la función como una referencia a una variable de ámbito global con la palabra clave global . mirada

Vamos a una versión modificada de su pseudocódigo para ver lo que sucede:

# Here, we're creating a variable 'x', in the __main__ scope. 
x = 'None!' 

def func_A(): 
    # The below declaration lets the function know that we 
    # mean the global 'x' when we refer to that variable, not 
    # any local one 

    global x 
    x = 'A' 
    return x 

def func_B(): 
    # Here, we are somewhat mislead. We're actually involving two different 
    # variables named 'x'. One is local to func_B, the other is global. 

    # By calling func_A(), we do two things: we're reassigning the value 
    # of the GLOBAL x as part of func_A, and then taking that same value 
    # since it's returned by func_A, and assigning it to a LOCAL variable 
    # named 'x'.  
    x = func_A() # look at this as: x_local = func_A() 

    # Here, we're assigning the value of 'B' to the LOCAL x. 
    x = 'B' # look at this as: x_local = 'B' 

    return x # look at this as: return x_local 

De hecho, se podría reescribir todos func_B con la variable llamada x_local y que funcionaría de forma idéntica.

El orden solo importa en cuanto al orden en que sus funciones realizan operaciones que cambian el valor de la x global. Por lo tanto, en nuestro ejemplo, el orden no importa, ya que func_B llama al func_A. En este ejemplo, el orden importa:

def a(): 
    global foo 
    foo = 'A' 

def b(): 
    global foo 
    foo = 'B' 

b() 
a() 
print foo 
# prints 'A' because a() was the last function to modify 'foo'. 

Tenga en cuenta que global solamente se requiere para modificar los objetos globales. Aún puede acceder a ellos desde dentro de una función sin declarar global. Por lo tanto, tenemos:

x = 5 

def access_only(): 
    return x 
    # This returns whatever the global value of 'x' is 

def modify(): 
    global x 
    x = 'modified' 
    return x 
    # This function makes the global 'x' equal to 'modified', and then returns that value 

def create_locally(): 
    x = 'local!' 
    return x 
    # This function creates a new local variable named 'x', and sets it as 'local', 
    # and returns that. The global 'x' is untouched. 

Nota la diferencia entre create_locally y access_only-access_only está accediendo a los x globales a pesar de no llamar global, y aunque create_locally no utiliza global bien, se crea una copia local desde es asignando un valor.

La confusión aquí es por qué no debe usar variables globales.

+0

No creo que esto sea muy confuso en la práctica, solo tiene que entender [las reglas de scoping de python] (http://stackoverflow.com/questions/291978/short-description-of-python-scoping-rules). – Darthfett

2

Aquí hay un caso que me atrapó, utilizando un valor global como valor predeterminado de un parámetro.

globVar = None # initialize value of global variable 

def func(param = globVar): # use globVar as default value for param 
    print 'param =', param, 'globVar =', globVar # display values 

def test(): 
    global globVar 
    globVar = 42 # change value of global 
    func() 

test() 
========= 
output: param = None, globVar = 42 

Esperaba que param tuviera un valor de 42. Sorpresa. Python 2.7 evaluó el valor de globVar cuando analizó por primera vez la función func. Cambiar el valor de globVar no afectó el valor predeterminado asignado a param. Retrasando la evaluación, como en el siguiente, funcionó como lo necesitaba.

def func(param = eval('globVar')):  # this seems to work 
    print 'param =', param, 'globVar =', globVar # display values 

O, si se quiere estar seguro,

def func(param = None)): 
    if param == None: 
     param = globVar 
    print 'param =', param, 'globVar =', globVar # display values 
0

puede acceder directamente a una variable global dentro de una función. Si desea cambiar el valor de esa variable global, use "global variable_name". Consulte el siguiente ejemplo:

var = 1 
def global_var_change(): 
     global var 
     var = "value changed" 
global_var_change() #call the function for changes 
print var 

En general, esta no es una buena práctica de programación. Al romper la lógica del espacio de nombres, el código puede ser difícil de comprender y depurar.

Cuestiones relacionadas