variables declaradas fuera de la función

Posible duplicado:
referenciado antes de error de asignación en python
var local referenciada antes de la asignación

Ok, solo estaba tratando de ver cómo funcionan los ámbitos de las variables y corrí en la siguiente situación. Todos corrieron desde la terminal:

x = 1 def inc(): x += 5 inc() Traceback (most recent call last): File "", line 1, in  File "", line 2, in inc UnboundLocalError: local variable 'x' referenced before assignment 

Así que estaba pensando bien, tal vez no tenga acceso a x en mi método, así que intenté:

  def inc(): print x 1 

Así que esto funciona. Ahora sé que podría hacer:

  def inc(): global x x += 1 

Y esto funcionaría. Pero mi pregunta es por qué falla el primer ejemplo. Quiero decir que esperaría, ya que en la print x funcionaba que x es visible dentro de la función, ¿por qué fallaba x + = 5?

A diferencia de los idiomas que emplean el scope léxico “verdadero”, Python opta por tener “espacios de nombres” específicos para las variables, ya sea global , nonlocal local o local. Se podría argumentar que hacer que los desarrolladores codifiquen conscientemente teniendo en cuenta dichos espacios de nombres es más explícito y, por lo tanto, más comprensible. Yo diría que tales complejidades hacen que el lenguaje sea más difícil de manejar, pero supongo que todo depende de las preferencias personales.

Aquí están algunos ejemplos con respecto a global :

 >>> global_var = 5 >>> def fn(): ... print(global_var) ... >>> fn() 5 >>> def fn_2(): ... global_var += 2 ... print(global_var) ... >>> fn_2() Traceback (most recent call last): File "", line 1, in  File "", line 2, in fn_2 UnboundLocalError: local variable 'global_var' referenced before assignment >>> def fn_3(): ... global global_var ... global_var += 2 ... print(global_var) ... >>> fn_3() 7 

Los mismos patrones también se pueden aplicar a variables nonlocal , pero esta palabra clave solo está disponible para las últimas versiones de Python.

En caso de que se lo pregunte, se usa la función nonlocal donde una variable no es global, pero no se encuentra dentro de la definición de la función que se está utilizando. Por ejemplo, una def dentro de una def , que es una ocurrencia común en parte debido a la falta de lambdas multi-statement. Sin embargo, hay un truco para eludir la falta de esta característica en los Pythons anteriores. Recuerdo vagamente que involucra el uso de una lista de un solo elemento …

Tenga en cuenta que escribir en variables es donde se necesitan estas palabras clave. Solo leer de ellos no es ambiguo, por lo tanto no es necesario. A menos que tenga una def interna, utilice los mismos nombres de variable que los externos, lo que debería evitarse para ser honesto.

Cuando Python analiza una función, observa cuando se realiza una asignación de variable. Cuando hay una asignación, se asume por defecto que esa variable es una variable local. Para declarar que la asignación se refiere a una variable global, debe utilizar la statement global .

Cuando accede a una variable en una función, su valor se busca mediante las reglas de scope de LEGB .


Entonces, el primer ejemplo

  x = 1 def inc(): x += 5 inc() 

produce un UnboundLocalError porque Python determinó que x en inc es una variable local,

Al acceder a x trabaja en tu segundo ejemplo.

  def inc(): print x 

porque aquí, de acuerdo con la regla LEGB, Python busca x en el ámbito local, no lo encuentra, luego lo busca en el ámbito extendido, aún no lo encuentra, y finalmente lo busca en el ámbito global con éxito.

Los nombres locales para una función se deciden cuando se define la función:

 >>> x = 1 >>> def inc(): ... x += 5 ... >>> inc.__code__.co_varnames ('x',) 

En este caso, x existe en el espacio de nombres local. La ejecución de x += 5 requiere un valor preexistente para x (para los enteros, es como x = x + 5 ), y esto falla en el tiempo de llamada de la función porque el nombre local no está UnboundLocalError razón por la UnboundLocalError se nombra la excepción UnboundLocalError como tal.

Compare la otra versión, donde x no es una variable local, por lo que puede resolverse en el ámbito global en su lugar:

 >>> def incg(): ... print(x) ... >>> incg.__code__.co_varnames () 

Preguntas similares en las preguntas frecuentes: http://docs.python.org/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value