As far as I understand variables initialised inside if statments are scoped to the function but the following code is throwing up UnboundLocalError: local variable 'seq_name' referenced before assignment errors
def scraper(filename):
if 'Identified secondary metabolite regions using strictness' in line:
seq_name = readfile[i + 1].split('_')[0]
if seq_name in line
I have shortend the code to contain only the relavent bits. I am unsure how to fix this error given that my understanding is correct. Please correct me if it is not.
Your understanding of scope is correct. Variables initialized inside if blocks are scoped to the enclosing function.
However, it's still possible (as is happening here) to skip the condition in which you assign the variable, and thus never have assigned it at all. UnboundLocalError: local variable 'seq_name' referenced before assignment is the error message for whenever a variable hasn't been assigned in the current scope yet, even when it could have been. You have to account for that possibility in your code - an else clause is the easiest way to do that.
Related
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 2 years ago.
I've been creating a series of random events where each function does something different to a main set of variables, yet I keep getting unbound local errors. Here's a watered down version of the barebones of my code
variable = 1
def main():
global variable
secondary()
variable = secondary()
def secondary()
variable += 1
return variable
once again this is a really minimal way to explain my code but the variable += 1 is the part that is expressing the error
I noted all of the same issues that #TimothyChen mentioned. I'd like to explain the error you're asking about, which is:
UnboundLocalError: local variable 'v' referenced before assignment
That happens here:
v = 1
def secondary()
v += 1
The issue here is due to a behavior that is unique to Python, and a little strange (please excuse that I changed the name variable to v to avoid confusion)...
If there is a global variable declared named v, and then you only read from a variable named v inside a function, Python declares that you are reading from the global variable named v.
If there is a global variable declared named v, and then you write to a variable named v inside a function, Python says that that's a different variable local to the function unless you first say global v in that function, after which point v refers to the global variable.
So the case of your function secondary(), you are A) writing to v in the function, and B) you don't say global v anywhere in the function. So Python says that inside that function, v is a unique variable local to that function. But if v is local to the function, and your first reference to the variable in that function is:
v += 1
then v hasn't been assigned a value prior to this point. Since this line of code first reads from v, and then writes a new value back to it, you get the error you're seeing because of the attempt to read from a variable that hasn't yet been assigned a value.
It seems pretty clear that what you need to do to fix this issue is to declare your secondary function as follows:
def secondary()
global variable
variable += 1
return variable
The addition of global variable tells Python that your reference to variable is referring to the global variable with that name, even though you are writing to it.
I would suggest that in the future, you not name variables variable. That can only lead to confusion.
In the secondary function, variable isn't defined. You would have to do global variable, which would make the variable accessible. Also, you call secondary twice, which would make the variable go up twice, not sure you would want that. Furthermore, secondary doesn't have a colon after the parentheses which creates a syntax error. Lastly, the code most likely isn't indented correctly, as the secondary variable is not indented, although the other code blocks are.
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.
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.
We discussed in my job about the following piece of Python code (maybe an anti-pattern):
if conditional_variable_:
a = "Some value"
print a
Supose conditional_variable was defined but a variable didn't.
The question is about using a variable without declaring it. The variable a is created inside a piece of code that maybe never will be executed but it is used.
Maybe that fix may repair the anti-pattern:
a = "default value"
if conditional_variable:
a = "changed_value"
print a
In that case, a variable was defined before use it. Consider print a like a ussage of the a variable.
It is not an anti-pattern. It is a bug.
Python has no 'declarations', only binding operations; a name is either bound, or it is not. Trying to access a name that hasn't been bound to yet results in an exception.
Unless your code specifically handles the exception and expected it, running into a NameError or UnboundLocalError exception should be considered a bug.
In other words, code that tries to reference a name should always be subject to the same conditions that bind the name, or be prepared to handle the exception that'll be raised if those conditions don't always hold. Giving your variable a default value outside the if statement means it is bound under all circumstances, so you can also reference it always.
I have a global variable I called Y_VAL which is initialized to a value of 2.
I then have a function, called f() (for brevity), which uses Y_VAL.
def f():
y = Y_VAL
Y_VAL += 2
However, when trying to run my code, python gives the error message:
UnboundLocalError: local variable 'Y_VAL' referenced before assignment
If I remove the last line Y_VAL += 2 it works fine.
Why does python think that Y_VAL is a local variable?
You're missing the line global Y_VAL inside the function.
When Y_VAL occurs on the right-hand-side of an assignment, it's no problem because the local scope is searched first, then the global scope is searched. However, on the left-hand-side, you can only assign to a global that way when you've explicitly declared global Y_VAL.
From the docs:
It would be impossible to assign to a global variable without global, although free variables may refer to globals without being declared global.
This is just how Python works: Assignment always binds the left-hand side name in the closest surrounding name space. Inside of a function the closest namespace is the local namespace of the function.
In order to assign to a global variable, you have to declare it global. But avoid global by all means. Global variables are almost always bad design, and thus the use of the global keyword is a strong hint, that you are making design mistakes.
I ran to the same issue as you and as many others like you, before realising it needs the global statement. I then decided to move everything to object orientation and have piece of mind. Call me insane but I just dont trust myself with the global statement and its not difficult to come against a problem of local scope that is a pain to debug.
So I would advice collect all your "global" variables put them in a class inside an init(self) and not only you wont have to worry about local scope but you will have your code much better organised. Its not a freak of luck that most programmer out there prefer OOP.