Volviendo variables en funciones Python no funciona bien

He estado intentando devolver una variable en una función en una variable y usarla fuera de ella:

test = 0 def testing(): test = 1 return test testing() print(test) 

Pero cuando lo ejecuto, el resultado es 0. ¿Cómo puedo solucionar este problema?

Estás arruinando un poco los ámbitos y / o asignación. Prueba esto:

 test = 0 def testing(): test = 1 return test test = testing() print(test) 

Explicación: La test dentro de testing es diferente a la test dentro del módulo. Debe asignarlo a nivel de módulo para obtener el resultado esperado.

Debido a que declara test en la función, no es una variable global, por lo tanto, no puede acceder a la test variable que creó en la función fuera de ella, ya que son ámbitos diferentes.

Si desea return test a una variable, tiene que hacer

 result = testing() print(result) 

O, también puede agregar una statement global :

 test = 0 def testing(): global test test = 1 return test testing() print(test) 

Por cierto, al hacer una statement condicional, no necesita los corchetes alrededor de 1==1 :).

Dentro de la función testing() , está creando una nueva test variable, sin referirse a la que ya existe. Si desea hacerlo, debe usar una statement global en la parte superior, como en:

 def testing(): global test ...etc... 

Su variable de test dentro de la función no tiene un scope global. Por lo tanto, si desea almacenar el valor de retorno en una variable y emitirlo después de eso, puede hacer algo como esto:

 result = testing() print(result) 

TLDR: se debe asignar un valor de return a algo en el sitio de la llamada.

 test = testing() 

Las funciones en Python tienen su propio scope. Se crea al ingresar (llamar) a la función, y se destruye cuando se abandona. La asignación a un nombre dentro de un scope hace que ese nombre sea local a este scope, causando que se destruya junto con el scope.

 # start outer scope test = 0 # create name outer:test def testing(): # start inner scope test = 1 # create name outer.testing:test return test # end inner scope # destroy name outer.testing:test testing() # new temporary inner scope outer.testing print(test) # use name outer:test # end outer scope 

En particular, los nombres en un ámbito interno pueden ” sombrear ” los nombres de un ámbito externo. Si bien la test del nombre existe tanto en las testing como en el ámbito externo, no se refiere a la misma cosa . Esto tiene dos implicaciones importantes:

  1. La asignación a la test interna no afecta a la test externa .
  2. Al final de la testing , la test interna se destruye y solo queda la test externa .

Esta es la razón por la que llamar a testing() no tiene el efecto deseado: nunca modifica la test externa aprobada para print .


La statement de return define el valor devuelto llamando a una función. No devuelve el nombre, solo el valor apuntado.

 def testing(): test = 1 # test refers to the value 1 return test # return test => value 1 

El valor devuelto por una función es como cualquier otro valor, ya sea desde un literal, una búsqueda u otro. Lo más importante es que el valor no persiste a menos que lo asigne a un nombre o lo use directamente.

 testing() # call test, discard its value test = testing() # call test, store its value as `test` print(testing()) # call test, use its value in `print` 

Entonces, para devolver algo de una función para su uso posterior, debe almacenar el resultado en un nombre. A continuación, puede utilizar ese nombre en una statement posterior. Un ejemplo mínimo para su caso se ve así:

 # we already can define testing here # it is overwritten later on, then def testing(): # all names we use inside of testing are gone at the end # if we just want a value, we can skip temporary names return 1 # store the return value of testing() for later use test = testing() print(test) 

Addendum: es posible que una función modifique el scope que lo contiene. Sin embargo, los nombres deben declararse explícitamente como provenientes de un ámbito externo.

Las palabras clave nonlocal y global permiten modificar nombres de ámbitos externos. Un nombre nonlocal es el nombre en el scope de la función coincidente más cercana. Un global es el nombre en el ámbito del módulo, independientemente de las funciones intermedias.

 test = 0 def increment(): global test # declare test as belonging to a specific scope test += 1 # no need to return something # we already modified the outer `test` print(test) # 0 increment() print(test) # 1 

Tenga en cuenta que la modificación de los nombres externos es a menudo el signo de un antipatrón, más para los datos global que los nonlocal . Más allá de los scripts pequeños, se vuelve difícil rastrear lo que está accediendo y modificando global mensajes global . A menudo, es más apropiado usar clases o generadores para mantener el estado.

Una función siempre puede leer nombres desde su ámbito de contenido, siempre que nunca escriba con el mismo nombre. Tales cierres son muy fáciles de crear, y la falta de modificación los hace más fáciles de rastrear. Tenga en cuenta que modificar un nombre en cualquier lugar de una función lo hace local, a menos que se declare global o nonlocal :

 test = 0 def increment(): global test test += 1 def show_test(): # we never modify `test`, so it is fetched from the outside print(test) def show_and_increment1(): # this function is broken! print(test) # `test` is *not* the outer one, since we modify it in the function test += 1 # modifying `test` makes it local for the *entire* function def show_and_increment2(): # this function works! global test # force `test` to be global print(test) test += 1 show_test() # 0 increment() show_test() # 1 show_and_increment2() # 1 show_and_increment2() # 2 show_and_increment2() # 3 show_test() # 4 show_and_increment1() # UnboundLocalError: local variable 'test' referenced before assignment