This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 16 days ago.
Code1:
# coding:utf-8
sum = 5
def add(x, y):
print sum
sum = x + y
if __name__ == '__main__':
add(7, 8)
When I run the code above, I got the following error:
ssspure:python ssspure$ python test.py
Traceback (most recent call last):
File "test.py", line 11, in <module>
add(7, 8)
File "test.py", line 6, in add
print sum
UnboundLocalError: local variable 'sum' referenced before assignment
Code2:
# coding:utf-8
sum = 5
def add(x, y):
sum = x + y
print sum
if __name__ == '__main__':
add(7, 8)
I can run code2 successfully.
I only moved the print sum below "sum = x + y" statement. Why did Code1 fail but Code2 runs successfully?
For code1:
You didn't declare sum. The sum you defined outside of the add function has no impact to the sum in you add function.
You can just put sum=0 in your function and that will work.
In fact, you are doing so in your code2. You innitialized sum as x+y
the issue is because the local and global variable are of same name . so the function will give preference to local variable first . since the local variable is not assigned it gives the error local variable is not assigned.
we can solve this issue by following ways:
1. use global keyword in the function
2. keep names different.
3. use function globals()
thanks
Related
This question already has answers here:
Using global variables in a function
(25 answers)
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 2 years ago.
num = 0
def func():
print(num)
func()
The above function is supposed to print the value held by variable num and it works. By this, i would assume that func has access of num. But when i try to change the value of num inside the function, it gives me an error. UnboundLocalError: local variable 'num' referenced before assignment
num = 0
def func():
print(num)
num += 1
func()
Why is this happening?
The num variable isn't in the function's local scope, so you can't modify it inside the function since the variable contains an immutable data type (int).
You can take advantage of global keyword or define the variable inside the function.
num = 0
def func():
global num
print(num)
num += 1
func()
This question already has answers here:
Python nested functions variable scoping [duplicate]
(10 answers)
Closed 5 years ago.
I have a two nested python functions, which look like this:
def outer():
t = 0
def inner():
t += 1
print(t)
inner()
Trying to call outer results in the following error:
>>> outer()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "sally.py", line 6, in outer
inner()
File "sally.py", line 4, in inner
t += 1
UnboundLocalError: local variable 't' referenced before assignment
I thought adding the line global t before t += 1 would help, except it didn't.
Why is this happening? How do I get around this problem, other than passing t to inner everytime I call it?
If using python 3, then using the nonlocal keyword would let the interpreter know to use the outer() function's scope for t:
def outer():
t = 0
def inner():
nonlocal t
t += 1
print(t)
inner()
If using python 2, then you can't directly assign to the variable, or it will make the interpreter create a new variable t which will hide the outer variable. You could pass in a mutable collection and update the first item:
def outer():
t = [0]
def inner():
t[0] += 1
print(t[0])
inner()
This question already has answers here:
Calling variable defined inside one function from another function
(6 answers)
Python: Variables aren't re-assigned
(2 answers)
Closed 7 years ago.
I tried the following and got an error message that "x is not defined".
def test():
x = 2
y = 3
return x
def main():
test()
print(2 + x)
main()
Why isn't it working?
x is defined in test, but not in main
This means that x is not defined in main's scope
Take a look at this question for more details regarding scope. Specifically this answer.
If you want to use the value assigned to x in test, you need to assign the return value of test to a name:
def main():
value_of_x_from_test = test() # This is the same as `x = 2` in `test`.
print(2 + value_of_x_from_test)
You need to assign x again, and the way to do that is say x = test(). The x from test only exists in x, which is why you need to reassign it.
It doesn't even have to be x, it could be y, or z: x is simply the name you return, the value you use in main() can be called anything!
Or, you can just call the function directly in main(), in which case you won't even need the first line in the main function:
def test():
x = 2
y = 3
return x
def main():
x = test()
print(2 + x) #or just `print(2 + test())`
main()
It's not working because of scope. X is defined in test, but not in main(). Try setting x = test() in main, and everything should work for you.
In order to get the value of x in main(), you have to assign it to something:
def main():
value = test() # The variable can be 'value' or any other valid name, including 'x'
print(2 + value)
Because of x is defined locally in test(), it cannot be used by main. Instead you can use directly the output of test as it is shown in the following code:
def main():
print(2 + test())
Could someone explain why the following program fails:
def g(f):
for _ in range(10):
f()
def main():
x = 10
def f():
print x
x = x + 1
g(f)
if __name__ == '__main__':
main()
with the message:
Traceback (most recent call last):
File "a.py", line 13, in <module>
main()
File "a.py", line 10, in main
g(f)
File "a.py", line 3, in g
f()
File "a.py", line 8, in f
print x
UnboundLocalError: local variable 'x' referenced before assignment
But if I simply change the variable x to an array, it works:
def g(f):
for _ in range(10):
f()
def main():
x = [10]
def f():
print x[0]
x[0] = x[0] + 1
g(f)
if __name__ == '__main__':
main()
with the output
10
11
12
13
14
15
16
17
18
19
The reason I am confused is, if from f() it can't access x, why it becomes accessible if x is an array?
Thanks.
But this answer says the problem is with assigning to x. If that's it,
then printing it should work just fine, shouldn't it?
You have to understand the order in which things happen. Before your python code is even compiled and executed, something called a parser reads through the python code and checks the syntax. Another thing the parser does is mark variables as being local. When the parser sees an assignment in the code in a local scope, the variable on the lefthand side of the assignment is marked as local. At that point, nothing has even been compiled yet--let alone executed, and therefore no assignment takes place; the variable is merely marked as a local variable.
After the parser is finished, the code is compiled and executed. When execution reaches the print statement:
def main():
x = 10 #<---x in enclosing scope
def f():
print x #<-----
x = x + 1 #<-- x marked as local variable inside the function f()
the print statement looks like it should go ahead and print the x in the enclosing scope (the 'E' in the LEGB lookup process). However, because the parser previously marked x as a local variable inside f(), python does not proceed past the local scope (the 'L' in the LEGB lookup process) to lookup x. Because x has not been assigned to in the local scope at the time 'print x' executes, python spits out an error.
Note that even if the code where an assignment occurs will NEVER execute, the parser still marks the variable on the left of an assignment as a local variable. The parser has no idea about how things will execute, so it blindly searches for syntax errors and local variables throughout your file--even in code that can never execute. Here are some examples of that:
def dostuff ():
x = 10
def f():
print x
if False: #The body of the if will never execute...
a b c #...yet the parser finds a syntax error here
return f
f = dostuff()
f()
--output:--
File "1.py", line 8
a b c
^
SyntaxError: invalid syntax
The parser does the same thing when marking local variables:
def dostuff ():
x = 10
def f():
print x
if False: #The body of the if will never execute...
x = 0 #..yet the parser marks x as a local variable
return f
f = dostuff()
f()
Now look what happens when you execute that last program:
Traceback (most recent call last):
File "1.py", line 11, in <module>
f()
File "1.py", line 4, in f
print x
UnboundLocalError: local variable 'x' referenced before assignment
When the statement 'print x' executes, because the parser marked x as a local variable the lookup for x stops at the local scope.
That 'feature' is not unique to python--it happens in other languages too.
As for the array example, when you write:
x[0] = x[0] + 1
that tells python to go lookup up an array named x and assign something to its first element. Because there is no assignment to anything named x in the local scope, the parser does not mark x as a local variable.
The reason is in first example you used an assignment operation, x = x + 1, so when the functions was defined python thought that x is local variable. But when you actually called the function python failed to find any value for the x on the RHS locally, So raised an Error.
In your second example instead of assignment you simply changed a mutable object, so python will never raise any objection and will fetch x[0]'s value from the enclosing scope(actually it looks for it firstly in the enclosing scope, then global scope and finally in the builtins, but stops as soon as it was found).
In python 3x you can handle this using the nonlocal keyword and in py2x you can either pass the value to the inner function or use a function attribute.
Using function attribute:
def main():
main.x = 1
def f():
main.x = main.x + 1
print main.x
return f
main()() #prints 2
Passing the value explicitly:
def main():
x = 1
def f(x):
x = x + 1
print x
return x
x = f(x) #pass x and store the returned value back to x
main() #prints 2
Using nonlocal in py3x:
def main():
x = 1
def f():
nonlocal x
x = x + 1
print (x)
return f
main()() #prints 2
The problem is that the variable x is picked up by closure. When you try to assign to a variable that is picked up from the closure, python will complain unless you use the global or nonlocal1 keywords. In the case where you are using a list, you're not assigning to the name -- You can modify an object which got picked up in the closure, but you can't assign to it.
Basically, the error occurs at the print x line because when python parses the function, It sees that x is assigned to so it assumes x must be a local variable. When you get to the line print x, python tries to look up a local x but it isn't there. This can be seen by using dis.dis to inspect the bytecode. Here, python uses the LOAD_FAST instruction which is used for local variables rather than the LOAD_GLOBAL instruction which is used for non-local variables.
Normally, this would cause a NameError, but python tries to be a little more helpful by looking for x in func_closure or func_globals 2. If it finds x in one of those, it raises an UnboundLocalError instead to give you a better idea about what is happening -- You have a local variable which couldn't be found (isn't "bound").
1python3.x only
2python2.x -- On python3.x, those attributes have changed to __closure__ and __globals__ respectively
The problem is in the line
x = x + 1
This is the first time x being assigned in function f(), telling the compiler that x is a local name. It conflicts with the previous line print x, which can't find any previous assignment of the local x.
That's where your error UnboundLocalError: local variable 'x' referenced before assignment comes from.
Note that the error happens when compiler tries to figure out which object the x in print x refers to. So the print x doesn't executes.
Change it to
x[0] = x[0] + 1
No new name is added. So the compiler knows you are referring to the array outside f().
This question already has answers here:
Using global variables in a function
(25 answers)
Closed last month.
From this code:
COUNT = 0
def increment():
COUNT = COUNT + 1
increment()
I get the following error:
Traceback (most recent call last):
File "test.py", line 6, in <module>
increment()
File "test.py", line 4, in increment
COUNT = COUNT+1
UnboundLocalError: local variable 'COUNT' referenced before assignment
Why? How can I increment the global variable COUNT from inside the function?
Use a global statement, like so:
COUNT = 0
def increment():
global COUNT
COUNT = COUNT+1
increment()
Global variables can be accessed without using global, but the statement is required in order to change the value of the global variable.
This is because globals don't bleed into the scope of the function. Use the global statement to force this for assignment:
>>> COUNT = 0
>>> def increment():
... global COUNT
... COUNT += 1
...
>>> increment()
>>> print(COUNT)
1
Note that using globals is a really bad idea - it makes code hard to read, and hard to use. Instead, return a value from your function (using return) and use that to do something. If the same data needs to be accessible from a range of functions, consider making a class.
It's also worth noting that CAPITALS is generally reserved for constants, so it's a bad idea to name global variables like this. For normal variables, lowercase_with_underscores is preferred.