Whenever I start my game and let's say for example I enter 1,4 as the grid reference it will reply with
"UnboundLocalError: local variable 'of' referenced before assignment"
How can I fix this?
Code (edited to for brevity):
import time
while 1==1:
cont=1
while cont==1:
of="-"
tf="-"
rf="-"
ov="-"
tv="-"
rv="-"
os="-"
ts="-"
rs="-"
go=1
...
Variable of (and all the other 2-letter variables) are not available in function xturn.
I strongly recommend that you use incremental programming: write a few lines of code, get those working, and then enlarge your program. This allows you to zero in on errors quite easily. Any time I attack a new style of programming, I find this quite useful. It appears that you're new to some of the techniques you're using here.
For instance, you're using in instead of == for comparisons. This is not going to work well as a general principle.
Declare your functions before the main program. The way you wrote this, you're redefining your functions every time you go through the loop. Moving functions to the top will cure you of many variable scoping problems, too.
Learn to use Boolean values and variables. Your loops should look like this:
while True:
cont = True
while cont:
You make variables available by passing them as arguments to the function. I can see that you're new to this, because you've given this function a parameter x that you never use.
Overall, you should not have 9 variables: you should have a list, and then just pass the entire list as the current state of the game board. If you number the squares 0-8, you can easily work with the board in that respect.
To solve the immediate problem, you can add this line to each of your routines:
global of,tf,rf,ov,tv,rv,os,ts,rs
This will make the variables available. I see that #Thomas has pointed this out.
Still, I encourage you to work on designing this more cleanly. Using global variables is generally bad design. Also, notice how much code you have to duplicate for this program? It should be a lot easier.
Accessing a variable inside one of your functions will basically work even if the variable is defined only in an outside scope. But in your xturn function, you have a line that assigns to of. It doesn't matter whether this line has been executed before the error occurs; its mere existence anywhere inside the function causes the Python interpreter to treat it as a local variable. Therefore, when accessing it in the if clause, Python tries to access a local variable of and now it does matter that such a local variable hasn't been assigned up until that point.
In your function xturn you use the variable of which is not declared / known in that scope, thus the error.
If you look at the stack trace:
Traceback (most recent call last):
File "D:/Projekte/Python/snakes35/blabla.py", line 141, in <module>
ocheck(1)
File "D:/Projekte/Python/snakes35/blabla.py", line 138, in ocheck
xturn(1)
File "D:/Projekte/Python/snakes35/blabla.py", line 33, in xturn
if goo in "1,4" and of not in "o":
UnboundLocalError: local variable 'of' referenced before assignment
you can figure that out via looking at the lines in your file, where the error ocures.
Related
I was attempting to make a game using Pygame, when implementing a function where the character shoots a projectile on the space bar being pressed, I came across an error:
File "/File/Path/Game.py", line 58 in draw_window
for block_bullet in block_bullet:
File "/File/Path/Game.py", line 123, in <module>
draw_window()
UnboundLocalError: local variable 'block_bullet' referenced before assignment
I have viewed other questions attempting to find an answer but could not find a solution
Here is a google docs link to the code:
https://docs.google.com/document/d/1YPIv3hIKtbTSORd_e4yRCCP9gIo_tJL6kzhIQHiodLI/edit?usp=sharing
I would like the 'Blocky' character to shoot these 'block_bullets' when the spacebar is pressed
In Python, any attempt to modify a variable within a function results in that variable being local to the function. In your draw_window function, the line of code for block_bullet in block_bullet: attempts to modify the block_bullet variable, which has the effect of referencing a local variable to which no value is assigned, producing that error.
You need to rename the first use of block_bullet in that function to some other name, resulting in the code for individual_bullet in block_bullet: indivdual_bullet.draw(win). (Any name that is not already used elsewhere in your program could work to replace individual_bullet in my example.)
Does UnboundLocalError occur only when we try to use assignment operators (e.g. x += 5) on a non-local variable inside a function or there other cases? I tried using methods and functions (e.g. print) and it worked. I also tried to define a local variable (y) using a global variable (x)
(y = x + 5) and it worked too.
Yes - the presence of the assignment operator is what creates a new variable (of the same name) in the current scope. Calling mutating methods on the old object are not a problem, nor is doing something with that old value, since there's no question (if only a single assignment was ever used) which value you're talking about.
The concern here is not the modification of a value. The concern is the ambiguity of the variable used. This can also be solved using the global keyword, which specifically tells Python to use the global version, eliminating the ambiguity.
Remember also that Python variables (or globals) are sort of hoisted, like in JavaScript. Any variable used inside a specific scope is a variable in that scope from the beginning of that scope. That means a variable used inside a function is a variable in that scope from the start of the function, regardless of if it shows up half way through.
A really good reference for this is here. Some more specifics here.
I am completely stumped. I looked at other answers to this same question, but none seemed to give the slightest answer as to why I myself am getting this error. I have pretty much 2 of the exact same programs running the same code with the exception of some URL's and Product ID's that it reads from files. The programs are a little bit long, so I put them on Pastebin Here. I don't expect you to read all the code, the error occurs in the main function where I define PID and then try to use it later in the function. Why does one work perfectly fine and the other does not? As far as I can see they are the same in that part, but maybe I missed something! Any help is appreciated!
Thanks!
PS: The error I receive is:
UnboundLocalError: Local variable 'PID' referenced before assignment
Your findall('CRC-START(.*?)CRC-END', PIDFile.read(), re.S) on line 202 didn't find anything, PID didn't get declared, boom, UnboundLocalError.
This happens because python interpreter makes a preliminary pass on the code, marking encountered variables as local, but it does not (and cannot) check if code that declares them will actually be executed.
Minimal reproducible example of that effect would be this:
>>> def foo():
if 0:
a = 1
print a
>>> foo()
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
foo()
File "<pyshell#4>", line 4, in foo
print a
UnboundLocalError: local variable 'a' referenced before assignment
(Rep not high enough to 'comment') Link doesn't work. Could you maybe provide the code excerpt?
This error occurs when you try to use a variable before it is initialized (or defined depending on your code) - when you try to use a variable outside of its scope. Make sure that your variable WILL be initialized by the reference point. I'm wondering if you put that in an if-statement that doesn't get entered...
First of all, it seems that you reassign a new list to PID every iteration of a for loop. In the end your PID will contain only the last result.
I think what you really want to do is assign an empty list to PID before the for loop. Maybe after output = open(outputFile, 'w') and then append results to PID every iteration. Then you will not get UnboundLocalError even if nothing is found in PID.txt.
I would like to write a function which receives a local namespace dictionary and update it. Something like this:
def UpdateLocals(local_dict):
d = {'a':10, 'b':20, 'c':30}
local_dict.update(d)
When I call this function from the interactive python shell it works all right, like this:
a = 1
UpdateLocals(locals())
# prints 20
print a
However, when I call UpdateLocals from inside a function, it doesn't do what I expect:
def TestUpdateLocals():
a = 1
UpdateLocals(locals())
print a
# prints 1
TestUpdateLocals()
How can I make the second case work like the first?
UPDATE:
Aswin's explanation makes sense and is very helpful to me. However I still want a mechanism to update the local variables. Before I figure out a less ugly approach, I'm going to do the following:
def LoadDictionary():
return {'a': 10, 'b': 20, 'c': 30}
def TestUpdateLocals():
a = 1
for name, value in LoadDictionary().iteritems():
exec('%s = value' % name)
Of course the construction of the string statements can be automated, and the details can be hidden from the user.
You have asked a very good question. In fact, the ability to update local variables is very important and crucial in saving and loading datasets for machine learning or in games. However, most developers of Python language have not come to a realization of its importance. They focus too much on conformity and optimization which is nevertheless important too.
Imagine you are developing a game or running a deep neural network (DNN), if all local variables are serializable, saving the entire game or DNN can be simply put into one line as print(locals()), and loading the entire game or DNN can be simply put into one line as locals().update(eval(sys.stdin.read())).
Currently, globals().update(...) takes immediate effect but locals().update(...) does not work because Python documentation says:
The default locals act as described for function locals() below:
modifications to the default locals dictionary should not be
attempted. Pass an explicit locals dictionary if you need to see
effects of the code on locals after function exec() returns.
Why they design Python in such way is because of optimization and conforming the exec statement into a function:
To modify the locals of a function on the fly is not possible without
several consequences: normally, function locals are not stored in a
dictionary, but an array, whose indices are determined at compile time
from the known locales. This collides at least with new locals added
by exec. The old exec statement circumvented this, because the
compiler knew that if an exec without globals/locals args occurred in
a function, that namespace would be "unoptimized", i.e. not using the
locals array. Since exec() is now a normal function, the compiler does
not know what "exec" may be bound to, and therefore can not treat is
specially.
Since global().update(...) works, the following piece of code will work in root namespace (i.e., outside any function) because locals() is the same as globals() in root namespace:
locals().update({'a':3, 'b':4})
print(a, b)
But this will not work inside a function.
However, as hacker-level Python programmers, we can use sys._getframe(1).f_locals instead of locals(). From what I have tested so far, on Python 3, the following piece of code always works:
def f1():
sys._getframe(1).f_locals.update({'a':3, 'b':4})
print(a, b)
f1()
However, sys._getframe(1).f_locals does not work in root namespace.
The locals are not updated here because, in the first case, the variable declared has a global scope. But when declared inside a function, the variable loses scope outside it.
Thus, the original value of the locals() is not changed in the UpdateLocals function.
PS: This might not be related to your question, but using camel case is not a good practice in Python. Try using the other method.
update_locals() instead of UpdateLocals()
Edit To answer the question in your comment:
There is something called a System Stack. The main job of this system stack during the execution of a code is to manage local variables, make sure the control returns to the correct statement after the completion of execution of the called function etc.,
So, everytime a function call is made, a new entry is created in that stack,
which contains the line number (or instruction number) to which the control has to return after the return statement, and a set of fresh local variables.
The local variables when the control is inside the function, will be taken from the stack entry. Thus, the set of locals in both the functions are not the same. The entry in the stack is popped when the control exits from the function. Thus, the changes you made inside the function are erased, unless and until those variables have a global scope.
Today I am facing a strange bug about the built in function min().
I noticed that was being rewritten during the execution of my program, so I started to look for in every function of the stack when min() gets overwritten (print(min.__module__)), and I got
UnboundLocalError: local variable 'min' referenced before assignment
I am still debugging and going back and forth between commits to check what is causing the problem. The program depends on different modules, but the modules are the same as the last time that the program was successful.
I wonder, how is it possible to delete the builtin "min"? I am sure I have not declared any variable with that name, and even if I had, the error would be different.
del min should restore the builtin (but in my case I get the error above)
builtins['min'] works (in 2 of the 3 systems where I tried)
Any idea of how this is possible?
In general, the cause of local variable referenced before assignment isn't that someone has deleted min, it's that you've assigned to a variable named min somewhere in your function after the point that you are receiving that error. (The assignment could also be in an if branch that wasn't taken, before the error, but in my experience the first scenario I proposed is more likely.)
Since you have assigned to it somewhere in the function and haven't declared it global, it is a local variable inside that function, and all uses of it refer to that local variable, not to the built-in function. You haven't assigned it a value yet, however, so Python doesn't know what value you want it to have.
Example:
def test():
x = min(1, 2, 3) # error message here
y = max(1, 2, 3)
# ... lots of code might go here
min = x if x < y else y # local assignment here
test()
The solution is simple. Don't do that. Use a name other than min for your own variable. In fact, it is good practice to avoid using the names of built-ins for your own purposes for this very reason.
You can delete it, but you'd have to do it explicitly:
>>> min(5,5)
5
>>> del __builtins__.min
>>> min(5,5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'min' is not defined
Just deleting it from within a function doesn't remove it from __builtins__, so your callee must be doing it on purpose