75

I don't know why when a is located in def test() it can not be found and gives the error

UnboundLocalError: cannot access local variable 'a' where it is not associated with a value

Code

import keyboard import time a = 0 def test(): a+= 1 print("The number is now ", a) time.sleep(1) while keyboard.is_pressed('i') == False: test() 

I tried setting a as global a or using a nonlocal modifier on it inside the def, but it doesn't seem to work. Is there a way I can get it to recognize a and run properly?

0

3 Answers 3

77

Python variables are scope based. This means one cannot access a value declared inside a function. But you can access a variable declared outside a function.

This would fail:

def func(): a = 1 func() print(a) 

This would print 1:

def func(): print(a) a = 1 func() 

Notice you can access it. You'll fail if you want to update it.

This would fail too:

def func(): a = a + 1 print(a) a = 1 func() 

You need to tell the interpreter to find variable a in the global scope.

def func(): global a a = a + 1 print(a) a = 1 func() 

Warning: It's not a good practice to use global variables. So better make sure the function is getting the value.

def func(a): a = a + 1 print(a) a = 1 func(a) 
Sign up to request clarification or add additional context in comments.

7 Comments

The last one doesn't work-- it doesn't increment the caller's a. So is the only solution the "not a good practice" solution using global variables?
It does. But not in global scope. Means you cannot call the func(a) multiple times to update a (since a is immutable). If you have a function that has to update a variable in global scope, you have other solutions other than global. You can update the value and return it.
It has nothing to do with a mutability. In the last function, a is updated in local scope and this have to be clear. You can't just say that It does. Since you have no return value in last function, you can do whatever you want with a but still, after function runs, the global a will still be a = 1. So the above comment is correct. The last function does not increment the caller's a when you run this program. At the a will still be `.
Also, if you have return what will change? Without storing the returned value, using return is pointless because parameters are isolated from global variables, and the function keeps working with the original value each time since the new value isn't preserved.
Exactly. That's what I wanted to say.
I'm pretty sure we are all on the same page with minor difference like, Once the value is returned one must store it in the variable in the global scope. But the explanation here is not a solution to the problem but a tutorial on what is the problem. So the OP can understand the concept and fix the problem. :)
@GeorgiosLivanos It has something with a being immutable. Say a was a list (a mutable type) and the last function happened to append a new value to the argument give to it (def func(a): a.append(1)). With the last function you would have an updated a with a new value appended to it. In global scope.
10

To access a global variable within a function you must specify it with global. Otherwise, the variable inside the function is a local variable that only has utility inside that function. That's why you get the error: "UnboundLocalError: local variable 'a' referenced before assignment". Inside the function you haven't defined the variable 'a' yet, either local or global.

import keyboard import time a = 0 def test(): global a a+= 1 print("The number is now ", a) time.sleep(1) while keyboard.is_pressed('i') == False: test() 

4 Comments

One CAN ACCESS a global variable from a function, but CANNOT UPDATE the value.
@MSH Can you explain why this is the case?
I do not know exactly why. It's a design choice. You need to do a research to understand why. Maybe it helps with memory management/garbage collection.
@MSH: that's wrong, you can modify a global variable inside a function.
2

You need to pass a to the function test. Python thinks as the a in the function as a local variable. This will work:

import keyboard import time a = 0 def test(a=a): a+= 1 print("The number is now ", a) time.sleep(1) while keyboard.is_pressed('i') == False: test() 

1 Comment

This doesn't work (assuming it's supposed to print an increasing series of numbers) -- it just prints 1 repeatedly.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.