x=5
def printx()
print x
x=10
running this gives unboundlocal error
but when my function is just print x i get no error..
Simply assigning a value to x in the function is making it a local variable, therefore shadowing the global x = 5 specified on the previous line. And on the line you're trying to print x, the local version of x hasn't been initialized yet. It is curious how doing something on a later line is influencing lines that come before it, but that's just how it works.
You don't need any special declaration to read a global variable, therefore it works without the assignment inside the function. However, if you'd rather assign 10 to the global x instead of making a new, local x, you'll have to specify global x inside the function.
Related
How interpreter of Python recognize undefined global variable (a) in function in the following code ?
def show():
print(a)
a = 1
show()
Python is interactive language, so it processes each line of code line by line.
Given this, it should throw an error at the line with undefined variable (print(a)).
However, it works without error.
How does interpreter of Python recognize the undefined variable (a) ?
Or is it just recognized as letters until show function is called?
I converted the above code to bytecode, but I didn't understand well it...
When you define your function inside a python interpreter, python treats it as a sort of black box. It initializes the variables that are not defined inside and outside the function as free variables. Then, it stores a reference to the function inside the global table (you can access it using globals()). This global table holds the values for global variables and global function references.
When you define the variable a python stores it inside the global dictionary as well. Just like the function before it.
After that when you call your function, python sees a variable a. It knows that the variable is free, therefore, must be declared inside the global variable by now. Then it looks up the global table and uses the value that is stored.
Python is run line by line, and in saying that, it will skip over the function until the function is called. So even though it's line by line, it's still running afterwards.
Use of global keyword:
To access a global variable inside a function, there is no need to use global keyword. As a is not assigned inside the function, python will look at the global scope.
We use global keyword to assign a new value to the global variable.
This example throws an error -
def show():
a = a + 5
print(a)
a = 1
show()
Error:
UnboundLocalError: local variable 'a' referenced before assignment
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.
The global keyword is used in a function to refer to a global variable within that function and modify it. However even if the global keyword is not used and if we just try to print the variable, python assumes it is the global variable that is being referred and simply prints that like so.
a = 2
def foo():
print(a)
foo()
the above code outputs 2. But the following code throws an error.
a = 2
def foo():
print(a)
a = 3
foo()
I get an UnboundLocalError saying local variable 'a' was referenced before assignment. Now since python is an interpreted language and execution happens one line at a time, shouldn't it first print the global value of a which is 2 (like in the first case) and then create a local variable with the same name ans assign it to 3. In the second case how does the interpreter know right at the print statement that I am referring to another variable 'a' in the next line? Why doesn't it behave in the same way as above?
PS: I do understand that using the global keyword can help me change the value of a from 2 to 3.
Python byte code is interpreted; Python source is first compiled to byte code.
Names are either local or global within a single scope, and that determination is made at compile time; you can't switch half way through a fuction. If there is any assignment to a in the function, it is local everywhere in the function unless you use global a.
a = 2
def foo():
global a
print(a)
a = 3
Without the global statement, print(a) refers to the local name a, even though it occurs before the actual assignment.
This question already has answers here:
Function not changing global variable
(4 answers)
Closed 5 years ago.
How does the code below give the output as None?
def funct(x):
x=7
x=11
x=test(x)
print(x)
Here is another code snippet:-
def func():
print (x)
x = 90
x = 1
func()
The output for this should be 90! The scope is searched as Local ,Enclosed , Global ,Build-in .Either x should here be searched as local or global
Please explain.
x here is not a global variable in the scope of the functions, as functions naturally create their own namespaces, which do not include any outer variables not passed in as a parameter.
There are many issues with your code, including the order of function calling, and the order of the operations inside the functions; but to answer your question in the broadest way possible, in order for you to access the x variable defined outside of your functions, in a greater scope that is, you need to reference its namespace, by prepending global x inside the body of each of your functions.
Read up on Python variables and scope, and recheck the other errors in your code I have stated above.
The first code snippet returns None for the simple fact that you didn't return any value from the function. You defined x as a local parameter, not a global variable. Since you didn't return any value, your call test(x) (which does not match the function name of funct), will become a value of None. This is clearly defined in the Python documentation. To get the local value back to your main program, try this:
test(x):
x = 7
return x
x = 11
x = test(x)
print(x)
Also, please note that your initial value of 11 is entirely ignored in the main program, and that your function ignores the value it's given. You should shorten this example to
func():
return 7
print(func())
Your second example will print the external value of 1 because you have not defined a local variable x at that point, and a function is allowed to reference global variables.
However, when you assign a value in the next, you create a local variable -- you have not declared x to be global, so you can't assign to the x in the main program.
Again, you do not return any value. Therefore, back in the main program, func() evaluates to None.
Does that clear up what happened?
If just got confronted with a weird issue in a program of mine. If simplified my code to the following:
def x(y="test"):
def xx():
if False:
y = "blubb"
print y
xx()
print y
x()
This throws the UnboundLocalError: referenced before assignment Error.
If i fix the code to the following:
def x(y="test"):
def xx():
print y
xx()
print y
x()
My code works again. I'm on Python 2.7.
I've just figured out, that the follow fix work as well and this is how i'm going to fix my software for the moment:
def x(y="test"):
def xx():
_y = y
if False:
_y = "blubb"
print _y
xx()
print y
x()
Check the LEGB rule in this answer for a general answer.
In your non-working first example, y is a Local variable, but it is not assigned and that raises an exception. The danger of not raising it would be much larger, as bugs in other cases could pass unnoticed easily (values for variables could be fetch from parent functions unwillingly).
In your second example, y is not a local variable, so by the LEGB rule the y variable is found in its parent function, and everything works.
The final example works because you use a local variable _y that it is always assigned.
The y variable created in the inner xx() function within the 'if' statement is overriding the outer y variable. Therefore when you call print y within xx(), it is referring to the local y variable which is unassigned.
Your fix works because now _y is a local variable and is always assigned before the print _y is reached.