Reputation: 300
I have two samples:
One:
import math
def my_function():
print(math.pi)
math.pi = 3
print(math.pi)
my_function()
Output:
3.141592653589793
3
Two:
a = 0
def my_function():
print(a)
a = 3
print(a)
my_function()
Output:
UnboundLocalError: local variable 'a' referenced before assignment
So what is the difference between them? I thought both math.pi
and a
were global in this case and it should produce UnboundLocalError
.
Upvotes: 3
Views: 309
Reputation: 1695
This has been answered a few times on SO before.
A variable is local to a function if there's a statement assigning it inside that function.
In your instance a = 3
defines a
as local variable inside of your function. The first print(a)
tries to access it, but it's not assigned a value yet.
That's why you see:
UnboundLocalError: local variable 'a' referenced before assignment.
The global instance created by a = 0
plays no role here.
Upvotes: 0
Reputation: 780673
In the first function, the variable is math
, not math.pi
. Since you're not assigning to math
, it doesn't become a local variable. Assigning to an attribute of a variable is not the same thing as assigning to the variable itself.
If you changed the function to
def my_function():
print(math.pi)
math = 3
print(math.pi)
you would get the same kind of error as in the second function:
UnboundLocalError: local variable 'math' referenced before assignment
Upvotes: 1
Reputation: 22021
If you do variable assignment within function the global variable would be ignored and won't be accessible within function execution, in sample with math
lib you do not override name math
itself, that's why it works. Snipped below would give you same error with math lib:
import math
def my_function():
print(math.pi)
math = 1
my_function()
You can use statement global before accessing variable, but if you will do any assignment later you will override global variable, so it's better to ALWAYS avoid doing that.
import math
def my_function():
global math
print(math.pi)
math = 1
print(math) # -> <module 'math' from ...
my_function() # -> 3.14159265359
print(math) # -> 1
Upvotes: 4