Uso de la palabra clave "global" en Python

285

Lo que entiendo al leer la documentación es que Python tiene un espacio de nombres separado para las funciones, y si quiero usar una variable global en esa función, necesito usarla global.

Estoy usando Python 2.7 y probé esta pequeña prueba

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

Parece que las cosas funcionan bien incluso sin ellas global. Pude acceder a la variable global sin ningún problema.

¿Me estoy perdiendo algo? Además, lo siguiente es de la documentación de Python:

Los nombres enumerados en una declaración global no deben definirse como parámetros formales o en un objetivo de control de bucle, definición de clase, definición de función o declaración de importación.

Si bien los parámetros formales y la definición de clase tienen sentido para mí, no puedo entender la restricción para el objetivo de control de bucle y la definición de función.

nik
fuente
1
Creo que está confundido con php, que requiere el uso de la palabra clave global, los documentos de Python lo confirman, básicamente si no está definido en el contexto local, se trata como global
tobyodavies
11
Tenga cuidado con su redacción: Python no tiene un espacio de nombres separado para las funciones (eso significaría que podría tenerlo def foo(): ...y foo = ...al mismo tiempo). Crea un nuevo alcance para cada llamada a la función. (Pero, ¿cómo se diferencia de casi cualquier otro idioma de forma remota de alto nivel en el mundo?)

Respuestas:

366

La palabra clave globalsolo 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 te 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 globalinstrucció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 puede usar globalpara declarar funciones, clases u otros objetos en un contexto local. Aunque recomendaría no hacerlo, ya que causa pesadillas si algo sale mal o necesita depuración.

unode
fuente
59
"global" en este contexto parece ser diferente de otros idiomas que se consideran "global". En Python, una referencia "global" todavía está dentro de los límites del módulo y necesitaría ser referenciada desde fuera de ese módulo como "module.global_var" en lugar de simplemente "global_var" como cabría esperar.
jugo
17
@juice - En Python no existe el absoluto globalsdefinido automáticamente en todos los espacios de nombres (afortunadamente). Como señaló correctamente, un global está vinculado a un espacio de nombres dentro de un módulo, sin embargo, puede importarse a otro módulo como from module import variableo import module.variable. En el primer caso, la importación haría accesible la variable variablesin requerir referencia como module.. Si se considera global en el alcance del módulo, dependerá de dónde se importe. Véase también nonlocalcomo una nueva palabra clave relacionada con el alcance en python 3.
unode
3
¿Podría explicar por qué las variables globales no son una buena solución? A menudo escucho esto, pero en mi proyecto actual parecen hacer exactamente lo que necesito que hagan. ¿Hay algo más siniestro en el que no haya pensado?
Robin Newhouse
55
@RobinNewhouse Hay algunas preguntas sobre SO que ya cubren ese tema y otros artículos que no son de SO .
Unode
213

Si bien puede acceder a las 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 su caso, solo está accediendo a la lista sub.

Ivo Wetzel
fuente
3
Con una advertencia: foo = 3sin trabajos globales, pero foo se define nuevamente localmente en el blubalcance de la función y no modifica la variable foo original. Esto fue bastante confuso para mí.
chhantyal
1
@chhantyal si por obras quieres decir que no arroja un error, estás en lo correcto, pero en el contexto de Ivo Wetzel no funcionaría como se esperaba. Hay usos para tal comportamiento, pero a menudo no es lo que el programador quiere.
Democidista
77

Esta es la diferencia entre acceder al nombre y vincularlo dentro de un ámbito.

Si solo está buscando una variable para leer su valor, tiene acceso a un 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 decirle 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 se vincule, lo que puede causar algunas consecuencias de aspecto bastante extraño (por ejemplo, UnboundLocalError aparece repentinamente en el 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
fuente
muy contrario a la intuición, es difícil creer que esto es válido el código Python
PlsWork
52

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

Considere esto, por ejemplo:

value = 42

def doit():
    print value
    value = 0

doit()
print value

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

La razón es que Python ha notado que, en otra parte de la función, se le asigna el nombre value, y tampoco valuese declara en ninguna parte global. Eso lo 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 algunos otros idiomas. Esencialmente, no puede acceder a una variable global si ha definido una variable local con el mismo nombre en cualquier lugar de la función.

un poco
fuente
1
Gracias por señalar esto. Por lo tanto, siempre que su ámbito local no se asigne a un nombre que exista fuera de él, las referencias en el ámbito local utilizarán el nombre externo. Sin embargo, si en alguna parte de su función asigna a ese nombre, las referencias en ese ámbito local, incluso antes de la asignación local, no miren hacia afuera.
Dmitry Minkovsky
1
Exactamente, lo tienes. global(o nonlocalen Python 3.x) anula este comportamiento y le permite reasignar el nombre externo.
poco
2
En otros idiomas, esto se conoce como "elevación", como por ejemplo: github.com/shichuan/javascript-patterns/blob/master/…
Dmitry Minkovsky
Para colmo de males, las variables declaradas con la palabra clave de la nueva JavaScript letson no izada.
poco el
¿Es más rápido acceder a una variable global declarada con globalo no importa?
mato
14

Acceder a un nombre y asignar un nombre son diferentes. En su caso, solo está accediendo a un nombre.

Si asigna a una variable dentro de una función, se asume que esa variable es local a menos que la declare global. En ausencia de eso, se supone que es global.

>>> x = 1         # global 
>>> def foo():
        print x       # accessing it, it is global

>>> foo()
1
>>> def foo():   
        x = 2        # local x
        print x 

>>> x            # global x
1
>>> foo()        # prints local x
2
usuario225312
fuente
7
  • Puede acceder a palabras clave globales sin palabra clave global
  • Para poder modificarlos, debe indicar explícitamente que la palabra clave es global. De lo contrario, la palabra clave se declarará en el ámbito local.

Ejemplo:

words = [...] 

def contains (word): 
    global words             # <- not really needed
    return (word in words) 

def add (word): 
    global words             # must specify that we're working with a global keyword
    if word not in words: 
        words += [word]
martynas
fuente
2

Se supone que cualquier variable declarada fuera de una función es global, es solo cuando se declaran desde dentro de las funciones (excepto los constructores) que debe especificar que la variable sea global.

Jesus Ramos
fuente
1

Esto se explica bien en las preguntas frecuentes de Python

¿Cuáles son las reglas para las variables locales y globales en Python?

En Python, las variables a las que solo se hace referencia dentro de una función son implícitamente globales. Si a una variable se le asigna un valor en cualquier lugar dentro del cuerpo de la función, se supone que es local a menos que se declare explícitamente como global.

Aunque un poco sorprendente al principio, un momento de consideración lo explica. Por un lado, la necesidad globalde variables asignadas proporciona una barra contra los efectos secundarios no deseados. Por otro lado, si globalfuera necesario para todas las referencias globales, estaría usando globaltodo el tiempo. Tendría que declarar como globalcada referencia a una función incorporada o a un componente de un módulo importado. Este desorden anularía la utilidad de la globaldeclaración para identificar los efectos secundarios.

https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python

user7610
fuente
0

Significa que no debe hacer lo siguiente:

x = 1

def myfunc():
  global x

  # formal parameter
  def localfunction(x):
    return x+1

  # import statement
  import os.path as x

  # for loop control target
  for x in range(10):
    print x

  # class definition
  class x(object):
    def __init__(self):
      pass

  #function definition
  def x():
    print "I'm bad"
ikostia
fuente
ikostia enumera todas las cosas que no puede usar 'x' por haber usado global - docs.python.org/reference/…
pycruft
1
@Unode: solo estoy demostrando todos los casos que NikhilRathod dio en su cita.
ikostia
0

Global hace que la variable "Global"

def out():
    global x
    x = 1
    print(x)
    return


out()

print (x)

Esto hace que 'x' actúe como una variable normal fuera de la función. Si eliminó el global, entonces daría un error ya que no puede imprimir una variable dentro de una función.

def out():
     # Taking out the global will give you an error since the variable x is no longer 'global' or in other words: accessible for other commands
    x = 1
    print(x)
    return


out()

print (x)
Miguel
fuente