Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UnboundLocalError with nested function scopes

I have code like this (simplified):

def outer():     ctr = 0      def inner():         ctr += 1      inner() 

But ctr causes an error:

Traceback (most recent call last):   File "foo.py", line 9, in <module>     outer()   File "foo.py", line 7, in outer     inner()   File "foo.py", line 5, in inner     ctr += 1 UnboundLocalError: local variable 'ctr' referenced before assignment 

How can I fix this? I thought nested scopes would have allowed me to do this. I've tried with 'global', but it still doesn't work.

like image 458
Thomas O Avatar asked Apr 09 '10 17:04

Thomas O


People also ask

How do you use variables in nested functions?

Nested functions can access variables of the enclosing scope. In Python, these non-local variables are read-only by default and we must declare them explicitly as non-local (using nonlocal keyword) in order to modify them. Following is an example of a nested function accessing a non-local variable.

What does UnboundLocalError mean in Python?

The Python "UnboundLocalError: Local variable referenced before assignment" occurs when we reference a local variable before assigning a value to it in a function. To solve the error, mark the variable as global in the function definition, e.g. global my_var .

How do you solve UnboundLocalError?

UnboundLocalError can be solved by changing the scope of the variable which is complaining. You need to explicitly declare the variable global. Variable x's scope in function printx is global. You can verify the same by printing the value of x in terminal and it will be 6.

What is non local variable in Python?

The nonlocal keyword is used to work with variables inside nested functions, where the variable should not belong to the inner function. Use the keyword nonlocal to declare that the variable is not local.


1 Answers

If you're using Python 3, you can use the nonlocal statement to enable rebinding of a nonlocal name:

def outer():     ctr = 0      def inner():         nonlocal ctr         ctr += 1      inner() 

If you're using Python 2, which doesn't have nonlocal, you need to perform your incrementing without barename rebinding (by keeping the counter as an item or attribute of some barename, not as a barename itself). For example:

... ctr = [0]  def inner():     ctr[0] += 1 ... 

and of course use ctr[0] wherever you're using bare ctr now elsewhere.

like image 64
Alex Martelli Avatar answered Oct 10 '22 22:10

Alex Martelli