¿Cómo cambiar una variable después de que ya está definida?

Estoy tratando de sumr o restar de una variable definida, pero no puedo averiguar cómo sobrescribir el valor antiguo con el nuevo.

a = 15 def test(): a = a +10 print ( a ) test() 

Mensaje de error:

 Traceback (most recent call last): File "test.py", line 7, in  test() File "test.py", line 4, in test a = a +10 UnboundLocalError: local variable 'a' referenced before assignment 

El error que obtiene cuando intenta ejecutar su código es:

 UnboundLocalError: local variable 'a' referenced before assignment 

… lo cual, a primera vista, parece extraño: después de todo, la primera statement en el código anterior ( a = 15 ) es una asignación. Entonces, ¿qué está pasando?

En realidad, están sucediendo dos cosas distintas, y ninguna de ellas es obvia a menos que usted ya sepa de ellas.

En primer lugar, tienes dos variables diferentes:

  • La a en su primera línea es una variable global (llamada así porque existe en el ámbito global, fuera de cualquier definición de función).

  • La a en las otras líneas es una variable local, lo que significa que solo existe dentro de la función test() .

Estas dos variables no están relacionadas entre sí, aunque tengan el mismo nombre.

Una variable es local a una función si hay una statement asignada dentro de esa función, por ejemplo, su a = a +10 línea.

Aun así, el error sigue pareciendo extraño: después de todo, lo primero que hace dentro de test() es asignar a a , así que, ¿cómo se puede hacer referencia de antemano?

La respuesta es que, en una statement de asignación, Python evalúa todo en el lado derecho del signo = antes de asignarlo al nombre en el lado izquierdo, por lo que aunque la asignación está escrita primero en su código, primero se hace referencia a en ese lado derecho: a +10 .

Hay dos maneras de evitar esto. La primera es decirle a Python que realmente quieres que a a inside test() sea ​​igual en el ámbito global:

 def test(): global a a = a + 10 print(a) 

Esto funcionará, pero es una forma bastante mala de escribir progtwigs. La modificación de las variables globales dentro de las funciones se hace difícil de administrar realmente rápido, porque generalmente tiene muchas funciones, y ninguna de ellas puede estar segura de que otra no esté jugando con la variable global de alguna manera que no están esperando.

Una mejor manera es pasar variables como argumentos a funciones, como esta:

 a = 15 def test(x): x = x + 10 print(x) test(a) 

Tenga en cuenta que el nombre no tiene que ser el mismo: su nueva definición de test() simplemente dice que acepta un valor y luego hace algo con él. Puede pasar cualquier cosa que desee, puede ser a , o el número 7 , o alguna otra cosa. De hecho, su código siempre será más fácil de entender si intenta evitar tener variables con el mismo nombre en diferentes ámbitos.

Si juegas con el código anterior, notarás algo interesante:

 >>> a = 15 >>> test(a) 25 >>> a 15 

… no ha cambiado! Esto se debe a que, aunque lo pasaste a test() y se asignó a x , fue entonces x que cambió, dejando solo el original.

Si desea cambiar realmente a , debe devolver su x modificada de la función y, a continuación, volver a asignarla a a en el exterior:

 >>> a = 15 >>> >>> def test(x): ... x = x + 10 ... print(x) ... return x ... >>> a = test(a) 25 >>> a 25 

Está modificando una variable creada en el scope de la función test() . Si desea que se modifique el valor externo, puede hacer lo siguiente:

 a = 15 def test(): global a a = a + 1 print(a) test() 

Lo haría de esta manera:

 def test(a): a = a +10 return a print(test(15)) 

Tenga en cuenta que en la versión propuesta aquí hay algunas cosas que difieren de la suya.

Primero, lo que escribí crearía una función que tiene, como entrada, el valor a (en este caso, establecido en 15 cuando llamamos a la función, ya definida en la última línea), luego asignamos al objeto un valor a (que fue 15) más 10, luego devuelve a (que ha sido modificado y ahora es 25) y, finalmente, imprime un agradecimiento a la última línea de código:

 print(test(15)) 

Tenga en cuenta que lo que hizo no era en realidad una función pura, por así decirlo. Por lo general, queremos que las funciones obtengan un valor de entrada (o varios) y devuelvan un valor de entrada (o varios). En su caso, tenía un valor de entrada que estaba realmente vacío y ningún valor de salida (ya que no usó retorno ). Además, trató de escribir esta entrada fuera de la función (que, cuando la llamó diciendo que test(a) el valor a no se cargó y le dio el error, es decir, en los ojos de la computadora que estaba “vacío”) .

Además, lo aliento a que se acostumbre a escribir retorno dentro de la función y luego a usar una impresión cuando la llame (tal como escribí en la última línea de encoding: print(test(15)) ) en lugar de usarla dentro de la función . Es mejor utilizar imprimir solo cuando llama a la función y desea ver qué está haciendo realmente la función.

Al menos, esta es la forma en que me mostraron en las lecciones básicas de progtwigción. Esto se puede justificar de la siguiente manera: si está utilizando el retorno dentro de la función, la función le dará un valor que podrá usar más adelante en otras funciones (es decir, el retorno de la función es algo con lo que puede trabajar). De lo contrario, solo se mostraría un número en la pantalla con una impresión , pero la computadora no podría seguir trabajando con ella.

PS Podrías hacer lo mismo haciendo esto:

 def test(a): a +=10 return a print(test(15)) 

El scope de la variable es local al bloque a menos que se defina explícitamente mediante la palabra clave global . Hay otra forma de acceder a la variable global local a una función usando la función global

 a = 15 def test(): a = globals()['a'] a += 10 print ( a ) test() 

El ejemplo anterior imprimirá 25 manteniendo el valor global intacto, es decir, 15 .

 # All the mumbo jumbo aside, here is an experiment # to illustrate why this is something useful # in the language of Python: a = 15 # This could be read-only, should check docs def test_1(): b = a + 10 # It is perfectly ok to use 'a' print(b) def test_2(): a = a + 10 # Refrain from attempting to change 'a' print(a) test_1() # No error test_2() # UnboundLocalError: ... 

Su error no tiene nada que ver con lo que ya se está definiendo … Una variable solo es válida dentro de su llamado ámbito: Si crea una variable en una función, solo se define en esta función.

 def test(): x=17 print(x) # returns 17 test() print(x) # results in an error.