global variable error in Python - python

I am learning Python on my own and I am baffled on what is wrong in the following code
glob_var = 0
def print_glob_var():
s = 0
while glob_var > 0:
s = s+1
glob_var = glob_var - 1
return s
#print (globvar)
def main():
global glob_var
glob_var = 4
print_glob_var()
main()
I am getting error "UnboundLocalError: local variable 'glob_var' referenced before assignment" . However when I use only the print the code block works fine.
What I am doing wrong. I am using Python 3.5.2

In order to change the value of a global variable inside a function, you must declare it global inside the function. You seem to do so in function main, but not in function print_glob_var.

Python analyses the body of print_glob_var, sees an assignment to glob_var (specifically glob_var = glob_var - 1) and no global statement, and decides based on that that glob_var is a local variable that it expects to see defined within the function. If you remove the assignment you will no longer get this error, although of course that creates new problems. Alternatively you could add global glob_var to the function. Including it in main is not enough, you need that statement everywhere the variable is used.
This is the kind of reason that using non-constant global variables in Python is a bad idea. Learn about classes.

glob_var = 4
def print_glob_var():
global glob_var # Set glob_var as global
s = 0
while glob_var > 0:
s = s+1 # You can do s += 1 here
glob_var = glob_var - 1
print(glob_var) # Your commented out print() was after the return statement
return s # so it would never be reached.
def main():
print_glob_var()
main()

Related

Why is this variable considered local?

I have this code:
with open("01-1-input.txt", "r") as f:
inputs = [int(i[:-2] if i[-1] == "n" else i) for i in f.readlines()]
total_mass = 0
def calculate_fuel_for_mass(mass):
fuel_for_mass = mass // 3 - 2
if fuel_for_mass > 0:
total_mass += fuel_for_mass
calculate_fuel_for_mass(fuel_for_mass)
else:
return 0
for i in inputs:
calculate_fuel_for_mass(i)
print(total_mass)
And it's throwing an UnboundLocalError: local variable 'total_mass' referenced before assignment.
Why is that? I thought any variable declared in the main scope is global?
The line
total_mass += fuel_for_mass
can be thought of as equivalent to
total_mass = total_mass + fuel_for_mass
Given a setup like this, python sees an assignment happening to a variable in local scope (inside the function).
A minimal demonstration of this behaviour can be seen as follows:
var = 42
def f():
var = var + 1
# var += 1 would also show the same behaviour
f() #UnboundLocalError: local variable 'var' referenced before assignment
Python infers that there is a local variable total_mass because it sees an assignment to the variable in the local scope.
However, the local variable total_mass has not been assigned a value,
and so you see the error as shown.
You can use the global keyword before the assignment to access the variable in the global scope as follows
var = 42
def f():
global var
var = var + 1
f() #var is now 43 in global scope
At the beginning of your function, put
global total_mass
For this, you have to know how variable scopes and mutable/immutable types in Python work. The int type is immutable, so when you try to "modify" it in the function, you essentially create a new variable with local scope. As the compiler can see that the variable is going to be local to the function, it assumes that you want to access the local variable in the first place, rather than the global one. It is possible to declare the variable global using the global keyword, however it's considered bad practice, as the program becomes harder to read and to debug.

Why is a global dictionary accessible inside a class whereas a global integer variable is not? [duplicate]

This question already has answers here:
Global dictionaries don't need keyword global to modify them? [duplicate]
(2 answers)
Why is the global keyword not required in this case? [duplicate]
(1 answer)
Closed 2 years ago.
I have declared a dictionary globally and a variable as well. Now, when accessing both in a class, I can access the dictionary but for accessing the other variable, I get the UnboundLocalError. For solving this, I used the line of code: global curr_length and then access it and it ran. But I wanted to known why is this additional line of code required for a normal integer variable whereas not required for a dictionary?
The code is:
memoized = {}
curr_length = 0
curr_pal = ""
class Solution:
def check_palindrome(self, str_):
if len(str_) <= 1:
return False
global curr_length
if len(str_) <= curr_length:
return False
if memoized.get(str_, None):
return memoized[str_]
if str_ == str_[::-1]:
memoized[str_] = True
curr_length = len(str_)
return True
memoized[str_] = False
return False
def longest_palindrome(self, str_, starting_index):
if len(str_) <= 1:
return None
n = len(str_)
if self.check_palindrome(str_[starting_index:n]):
return str_
n -= 1
self.longest_palindrome(str_[starting_index:n], starting_index)
def longestPalindrome(self, s: str) -> str:
for starting_index in range(len(s)):
pal = self.longest_palindrome(s, starting_index)
if pal:
return pal
return ""
solution = Solution()
print(solution.longestPalindrome("babad"))
Short:
You are trying to change the value of curr_length with curr_length = len(str_) inside a function which looks for a local curr_length variable, and can't find it. It needs the line global curr_length to know that it's a global variable.
As far as why you're wondering as to why a dict object does not need global memoized line, you should read the answer to:
Global dictionaries don't need keyword global to modify them? or Why is the global keyword not required in this case?
EXPLANATION:
In Python, a variable declared outside of the function or in global scope is known as global variable. This means, global variable can be accessed inside or outside of the function.
Let's see an example on how a global variable is created in Python.
x = "global"
def foo():
print("x inside :", x)
foo()
print("x outside:", x)
When we run the code, the will output be:
x inside : global
x outside: global
In above code, we created x as a global variable and defined a foo() to print the global variable x. Finally, we call the foo() which will print the value of x.
What if you want to change value of x inside a function?
def foo():
x = x * 2
print(x)
foo()
When we run the code, the will output be:
UnboundLocalError: local variable 'x' referenced before assignment
The output shows an error because Python treats x as a local variable and x is also not defined inside foo().
To make this work we use global keyword

Python Global Variables for Recursive Function

In my math class, we have been told to write a program in python. In one of the parts, I want to test the convergence of a series. While writing the program, I realized I was fundamentally misunderstanding something about how python handles global variables. Take this code:
def main():
global n
n = 1
def check():
a = 10
if n > a: print(n)
else: n += 1
check()
main()
This code fails because it says that n has not been defined yet. However, I can't define n inside of the check() function since that would just reset n to one upon every iteration! Is there some workaround for this problem?
As already stated in the comments, n isn't in the global scope yet, since it's inside the nested function check. You will need to add global n to the check's scope, to access the global n value from the nested function:
def main():
global n
n = 1
def check():
global n
a = 10
if n > a: print(n)
else: n += 1
check()
main()
#PedrovonHertwig also pointed out you don't need global n in main (which is the case in your current context, ignore this if you want to use n elsewhere in the top-level scope) and thatn is perfectly fine staying in main's local scope. You can then replace the global keyword inside check to nonlocal n, telling python to use the n that is not in the local scope nor the global scope, but main's scope.

Global Variables in functions with if statements

Okay, I am currently doing a project to make a blackjack game in python and I'm having some trouble. One of my issues is I dont know when to define a variable as global, specifically in functions with if statements. If I have a global variable outside the if statement, do I have to claim that the variable is global within the if statement as well? For example:
x = 5
def add():
global x <--- ?
x += 1
if x == 7:
global x <--- ?
x = 5
I'm pretty sure I need the "global x" at the 1st question mark, but what about at the second question mark? Would I still need to put a "global x" within my if statement if I wanted my if statement to update a global variable? Or does the global x at the beginning of the function make the x's inside the if statement global? Also, if I wanted to return x here, where should I do it?
Only one global statement is enough.
From docs:
The global statement is a declaration which holds for the entire
current code block.
x = 5
def add():
global x
x += 1
if x == 7:
x = 5
Also, if I wanted to return x here, where should I do it?
If you're using global in your function then the return x must come after the global x statement, if you didn't use any global statement and also didn't define any local variable x then you can return x anywhere in the function.
If you've defined a local variable x then return x must come after the definition.

Python global/local variables

Why does this code work:
var = 0
def func(num):
print num
var = 1
if num != 0:
func(num-1)
func(10)
but this one gives a "local variable 'var' referenced before assignment" error:
var = 0
def func(num):
print num
var = var
if num != 0:
func(num-1)
func(10)
Because in the first code, you have created a local variable var and used its value, whereas in the 2nd code, you are using the local variable var, without defining it.
So, if you want to make your 2nd function work, you need to declare : -
global var
in the function before using var.
def func(num):
print num
var = 1 <-- # You create a local variable
if num != 0:
func(num-1)
Whereas in this code:
def func(num):
print num
var = var <--- # You are using the local variable on RHS without defining it
if num != 0:
func(num-1)
UPDATE: -
However, as per #Tim's comment, you should not use a global variable inside your functions. Rather deifine your variable before using it, to use it in local scope. Generally, you should try to limit the scope of your variables to local, and even in local namespace limit the scope of local variables, because that way your code will be easier to understand.
The more you increase the scope of your variables, the more are the chances of getting it used by the outside source, where it is not needed to be used.
If you have var = ... anywhere in a function, the name "var" will be treated as a local variable for the entire function, regardless of where that assignment occurs. This means that all occurrences of var in your function will be resolved in the local scope, so the right hand side of var = var results in the referenced before assignment error because var has not yet been initialized in the function's scope.
You can read a global without declaring it global. But to write a global, you need to declare it global.
In your second piece of code you have created a local variable in RHS and without defining it, you are assigning it to the LHS variable var which is global (a variable defined outside the function is considered global explicitly).
If your intention is to create a local variable inside the function and assign it to the value of the global variable, this will do the trick:
var = 0
def func(num):
print num
func.var = var # func.var is referring the local
# variable var inside the function func
if num != 0:
func(num-1)
func(10)
def runscan(self):
p = os.popen('LD_PRELOAD=/usr/libv4l/v4l1compat.so zbarcam
/dev/video0','r')
def input(self):
self.entryc.insert(END, code)
how about this?
i want use local 'code' to the next function to insert the result of barcode to my Tkinter entryBox..
Thanks
Each function block is a local scope. If you want to assign to global variables, you need to do so explicitly:
var = 0
def func(num):
print num
global var
var = 1
if num != 0:
func(num-1)
print var # 0
func(2)
print var # 1

Categories