¿Por qué la asignación a mis variables globales no funciona en Python?

Resuelto Free Wildebeest asked hace 15 años • 6 respuestas

Estoy teniendo terribles problemas al tratar de comprender las reglas de alcance de Python.

Con el siguiente guión:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

Da el resultado inesperado (para mí) de:

    Antes del conjunto A
    El valor de a es 7.
    Dentro de setA, a ahora es 42
    Después del conjunto A
    El valor de a es 7.

Donde esperaría que la última impresión del valor de a fuera 42, no 7. ¿Qué me falta acerca de las reglas de alcance de Python para el alcance de las variables globales?

Free Wildebeest avatar May 30 '09 21:05 Free Wildebeest
Aceptado

Las variables globales son especiales. Si intenta asignar una variable a = valuedentro de una función, crea una nueva variable local dentro de la función, incluso si hay una variable global con el mismo nombre. Para acceder a la variable global, agregue una globaldeclaración dentro de la función:

a = 7
def setA(value):
    global a   # declare a to be a global
    a = value  # this sets the global value of a

Consulte también Denominación y vinculación para obtener una explicación detallada de las reglas de denominación y vinculación de Python.

Adam Rosenfield avatar May 30 '2009 14:05 Adam Rosenfield

El truco para entender esto es que cuando asignas una variable, usando =, también la declaras como una variable local. Entonces, en lugar de cambiar el valor de la variable global a, setA(value) en realidad establece una variable local (que se llama a) con el valor pasado.

Esto se vuelve más obvio si intentas imprimir el valor de a al comienzo de setA(value) de esta manera:

def setA(value):
    print "Before assignment, a is %d" % (a)
    a = value
    print "Inside setA, a is now %d" % (a)

Si intenta ejecutar este Python, obtendrá un error útil:

Rastreo (llamadas recientes más última):
  Archivo "scopeTest.py", línea 14, en
    establecerA(42)
  Archivo "scopeTest.py", línea 7, en setA
    print "Antes de la asignación, a es %d" % (a)
UnboundLocalError: variable local 'a' a la que se hace referencia antes de la asignación

Esto nos dice que Python ha decidido que la función setA(value) tiene una variable local llamada a, que es lo que modificas cuando le asignas la función. Si no asigna a a en la función (como con printA()), Python usa la variable global A.

Para marcar una variable como global, debe usar la palabra clave global en Python, en el ámbito en el que desea usar la variable global . En este caso, eso está dentro de la función setA(valor). Entonces el guión se convierte en:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    global a
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

Esta adición de una línea le dice a Python que cuando usas la variable a en la función setA(value) estás hablando de la variable global, no de una variable local.

Free Wildebeest avatar May 30 '2009 14:05 Free Wildebeest