¿Por qué no se necesita la palabra clave "global" para acceder a una variable global?

Resuelto nik asked hace 13 años • 11 respuestas

Según tengo entendido, Python tiene un espacio de nombres separado para funciones, por lo que si quiero usar una variable global en una función, probablemente debería usar global.

Sin embargo, pude acceder a una variable global incluso sin global:

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'

¿Por qué funciona esto?


Consulte también UnboundLocalError en la variable local cuando se reasigna después del primer uso para conocer el error que se produce al intentar asignar a la variable global sin global. Consulte Uso de variables globales en una función para conocer la pregunta general sobre cómo usar variables globales.

nik avatar Jan 14 '11 23:01 nik
Aceptado

La palabra clave globalsólo es útil para cambiar o crear variables globales en un contexto local, aunque la creación de variables globales rara vez se considera una buena solución.

def bob():
    me = "locally defined"    # Defined only in local context
    print(me)

bob()
print(me)     # Asking for a global variable

Lo anterior le dará:

locally defined
Traceback (most recent call last):
  File "file.py", line 9, in <module>
    print(me)
NameError: name 'me' is not defined

Mientras que si usa la globaldeclaración, la variable estará disponible "fuera" del alcance de la función, convirtiéndose efectivamente en una variable global.

def bob():
    global me
    me = "locally defined"   # Defined locally but declared as global
    print(me)

bob()
print(me)     # Asking for a global variable

Entonces el código anterior te dará:

locally defined
locally defined

Además, debido a la naturaleza de Python, también puedes usarlo globalpara declarar funciones, clases u otros objetos en un contexto local. Aunque lo desaconsejaría ya que causa pesadillas si algo sale mal o necesita depurarse.

unode avatar Jan 14 '2011 16:01 unode

Si bien puede acceder a variables globales sin la globalpalabra clave, si desea modificarlas debe usar la globalpalabra clave. Por ejemplo:

foo = 1
def test():
    foo = 2 # new local foo

def blub():
    global foo
    foo = 3 # changes the value of the global foo

En tu caso, recién estás accediendo a la lista sub.

Ivo Wetzel avatar Jan 14 '2011 16:01 Ivo Wetzel

Ésta es la diferencia entre acceder al nombre y vincularlo dentro de un alcance.

Si solo está buscando una variable para leer su valor, tiene acceso al alcance global y local.

Sin embargo, si asigna a una variable cuyo nombre no está en el ámbito local, está vinculando ese nombre a este ámbito (y si ese nombre también existe como global, lo ocultará).

Si desea poder asignar el nombre global, debe indicarle al analizador que use el nombre global en lugar de vincular un nuevo nombre local, que es lo que hace la palabra clave 'global'.

La vinculación en cualquier lugar dentro de un bloque hace que el nombre en todas partes de ese bloque quede vinculado, lo que puede causar algunas consecuencias bastante extrañas (por ejemplo, UnboundLocalError aparece repentinamente en un código que funcionaba anteriormente).

>>> a = 1
>>> def p():
    print(a) # accessing global scope, no binding going on
>>> def q():
    a = 3 # binding a name in local scope - hiding global
    print(a)
>>> def r():
    print(a) # fail - a is bound to local scope, but not assigned yet
    a = 4
>>> p()
1
>>> q()
3
>>> r()
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    r()
  File "<pyshell#32>", line 2, in r
    print(a) # fail - a is bound to local scope, but not assigned yet
UnboundLocalError: local variable 'a' referenced before assignment
>>> 
pycruft avatar Jan 14 '2011 16:01 pycruft

Las otras respuestas responden a tu pregunta. Otra cosa importante que debe saber sobre los nombres en Python es que son locales o globales según el ámbito.

Considere esto, por ejemplo:

value = 42

def doit():
    print value
    value = 0

doit()
print value

Probablemente puedas adivinar que la value = 0declaración se asignará a una variable local y no afectará el valor de la misma variable declarada fuera de la doit()función. Es posible que se sorprenda aún más al descubrir que el código anterior no se ejecutará. La declaración print valuedentro de la función produce unaUnboundLocalError.

La razón es que Python ha notado que, en otra parte de la función, le asignas el nombre value, y además valueno está declarado en ninguna parte global. Eso la convierte en una variable local. Pero cuando intenta imprimirlo, el nombre local aún no se ha definido. Python en este caso no recurre a buscar el nombre como una variable global, como lo hacen otros lenguajes. Básicamente, no puede acceder a una variable global si ha definido una variable local con el mismo nombre en cualquier parte de la función.

kindall avatar Jan 14 '2011 18:01 kindall