free variable referenced before assignment in enclosing scope - python

Hey im having some trouble understanding what I did wrong/finding a way to fix it, can you guys help me?
def main():
Keys = 0
def Function1():
global all
def Function2():
global all
print(str(Keys))
Function2()
Keys = Keys + 1
Function1()
main()
every time i try to run this i get this error "free variable 'Keys' referenced before assignment in enclosing scope"
Thanks in advance!

You need to define global Keys for every function. A function thinks that Keys is a local variable.
def main():
global Keys
Keys = 0
def Function1():
global Keys
global all
def Function2():
global Keys
global all
print(str(Keys))
Function2()
Keys = Keys + 1
Function1()
main()
However, using global is bad. Here are a list of reasons why using global is bad
So, instead of using global, you can pass it as an parametre.
def main():
Keys = 0
def Function1(Keys):
def Function2(Keys):
print(str(Keys))
Function2(Keys)
Keys = Keys + 1
Function1(Keys)
main()
Also, all is a function in python. There is absolutely no need to make it global

Related

using same variable that is created in function into another function

I want to use 'number' variable that was created out of the function and use it in couple functions and also give it an initial value 0, but it gives "local variable 'number' referenced before assignment" error at the last line of code.How could I fix it?Thanks in advance.
lst_img=[img0,img1,img2,img3,img4]
number=0
def go_forward():
global number
number+=1
shwimage.grid_forget()
global shwimage1
shwimage1=Label(image=lst_img[number])
shwimage1.grid(row=0,column=0,columnspan=3)
def go_back():
if number==0:
shwimage.grid_forget()
shwimage1.grid_forget()
shwimage2=Label(image=lst_img[number-1])
shwimage2.grid(row=0,column=0,columnspan=3)
number-=1 # local variable 'number' referenced before assignment
You have to also tell go_back() to use the global variable:
def go_back():
global number #add this
if number==0:
shwimage.grid_forget()
shwimage1.grid_forget()
shwimage2=Label(image=lst_img[number-1])
shwimage2.grid(row=0,column=0,columnspan=3)
number-=1 # local variable 'number' referenced before assignment
global tells the function to use the global number so each function has to be told this separately or it will default to using the local version.
I believe in go_back() function also, you are trying to reference the global variable number But it is not instructed to the function to use global number variable.
def go_back():
global number #This line needs to be addded
if number==0:
shwimage.grid_forget()
shwimage1.grid_forget()
shwimage2=Label(image=lst_img[number-1])
shwimage2.grid(row=0,column=0,columnspan=3)
number-=1
The others answers' solution to add global number in go_back is working, but using global variables is really not a good practice when you can do otherwise.
What you could do here is use object oriented programming. Create a class with a number, lst_img and showimage properties and two class methods, go_forward and go_backward, that can modifiy the number and showimage properties.
How I would start :
class ImageViewer:
# Class constructor
def __init__(self, lst_img):
self.lst_img = lst_img
self.number = 0 # number is always 0 at the beginning
self.showimage = None
def go_forward(self):
if self.number == len(self.lst_img)-1 :
return
else:
self.number += 1
# ... add your code ....
if self.showimage is None:
# code to create a showimage...
self.showimage = .....
else:
# code to update the showimage...
def go_backward(self):
if self.number == 0:
return
else :
self.number -= 1
if self.showimage is None:
# code to create a showimage...
self.showimage = .....
else:
# code to update the showimage...
# Create an viewer instance with a list of images
lst_img = [img1, img2, img3]
viewer = ImageViewer(lst_img)
# Now you can use the go_forward and go_backward methods to naviguate in your images
viewer.go_forward()
viewer.go_forward()
viewer.go_backward()
....
A reason you get the error, local variable 'number' referenced before assignment, is you did not used global keyword to declare that you will use THE number variable even in go_back().
A simple solution is to use global in the go_back(), as follows:
def go_back():
global number # -> as you did in `go_forward()`.
if number==0:
shwimage.grid_forget()
shwimage1.grid_forget()
shwimage2=Label(image=lst_img[number-1])
shwimage2.grid(row=0,column=0,columnspan=3)
number-=1 # local variable 'number' referenced before assignment
However, you need to play it safe when using global because it makes hard to track variable changes. Instead, it would be better to pass number value as an argument in the functions.
For more information to use global keyword, see an answer of the question here: Why are global variables evil?
In addition, I recommend you to read this article, Alternatives to Using Globals in Python
The problem is that you are using the number variable as global variable.
Use global number in both of your functions:
lst_img=[img0,img1,img2,img3,img4]
number=0
def go_forward():
global number
number+=1
shwimage.grid_forget()
global shwimage1
shwimage1=Label(image=lst_img[number])
shwimage1.grid(row=0,column=0,columnspan=3)
def go_back():
global number
if number==0:
shwimage.grid_forget()
shwimage1.grid_forget()
shwimage2=Label(image=lst_img[number-1])
shwimage2.grid(row=0,column=0,columnspan=3)
number-=1

assigning values to global variables in python [duplicate]

This question already has answers here:
Using global variables in a function
(25 answers)
Closed 1 year ago.
Sorry for the beginner question. In the below code, the output I'm getting is "Original" and not "Function". Doesn't the value of name change after passing through the function? Thanks
global name
name = "Original"
def test():
name = "Function"
test()
print(name)
Use the global keyword in the function.
name = "Original" # define name
def test(): # define our function
global name # this function can now change name
name = "Function" # change the value
test() # run the function
print(name) # returns Function
I'd assume global needs to be in the function so you could do something like this, where a function can use text without effecting the text var:
text = "Original"
def test():
global text
text = "Function"
def printText(text):
textToPrint = text # use text var without any issues in this function
print(textToPrint)
test()
print(text)
global declarations go inside the function you want to apply them to, not at the top-level.
name = "Original"
def test():
global name
name = "Function"
test()
print(name)
name = "Original" #global variable
def test():
#to update the global value you have to declare it here
global name
name = "Function"
test()
print(name)
you can read more about it here, https://www.programiz.com/python-programming/global-keyword

Python UnboundLocalError, what causes it?

In python I wrote:
registered_to = 0
def execute_data():
registered_to += response.text.count("<div class=\"info-msg\">")
But I'm getting:
registered_to += response.text.count("<div class=\"info-msg\">")
UnboundLocalError: local variable 'registered_to' referenced before assignment
Is this what you want?
registered_to = 0
def execute_data():
global registered_to
registered_to += response.text.count("<div class=\"info-msg\">")
global keyword must be used whenever you wish to modify/create global variables from a non-global scope like a function. If you are just using a global variable from a non-global scope and not modifying it, you need not use the keyword.
Examples
Using global variable in a non-global scope but not modifying it
wish = "Hello "
def fun():
print(wish)
fun()
Using global variable in a non-global scope and modifying it as well
wish = "Hello "
def fun():
word += "World"
print(wish)
fun()

Python 3: Suspect_ID is not defined

I'm currently working on a town of salem-esc project for a class but I've ran into an issue. I have been trying to make it so that Suspect_ID is available globally but for some reason it is instead saying ("name 'Suspect_ID' is not defined", I'm tried making it outside of the statement with the rest of my global variables to no avail as well. Any suggestions would be helpful, and if any other information is needed feel free to ask, I hope you have better luck with this program than I am currently having.
def readinSuspects():
#local variables
global Suspect_name
Suspect_name=["","","","","","","","","",""]
global Suspect_age
Suspect_age=[0,0,0,0,0,0,0,0,0,0]
global Suspect_motive
Suspect_motive=["","","","","","","","","",""]
global Suspect_ID
Suspect_ID=[0,0,0,0,0,0,0,0,0,0]
global IsMurderer
IsMurderer=[False,False,False,False,False,False,False,False,False,False]
#subprogram body
file = open("suspects.txt","r")
for i in range(0,9):
Suspect_name[i],Suspect_age[i],Suspect_motive[i],
Suspect_ID[i]=file.readline().split(',')
return Suspect_name,Suspect_age,Suspect_motive,Suspect_ID,IsMurderer
edit: I'm now realising the issue may lie elsewhere so following is gonna be the program in it's entirety, it's far from finished and I am aware there are many other bugs etc.
import random
#Global variable
Guesses=[0]
Murderer=[0]
#Read In Function
def readinSuspects():
#local variables
global Suspect_name
Suspect_name=["","","","","","","","","",""]
global Suspect_age
Suspect_age=[0,0,0,0,0,0,0,0,0,0]
global Suspect_motive
Suspect_motive=["","","","","","","","","",""]
global Suspect_ID
Suspect_ID=[0,0,0,0,0,0,0,0,0,0]
global IsMurderer
IsMurderer=[False,False,False,False,False,False,False,False,False,False]
#subprogram body
file = open("suspects.txt","r")
for i in range(0,9):
Suspect_name[i],Suspect_age[i],Suspect_motive[i],
Suspect_ID[i]=file.readline().split(',')
return Suspect_name,Suspect_age,Suspect_motive,Suspect_ID,IsMurderer
#randomly assign murderer
readinSuspects(Suspect_ID)
Murderer = random.randint(0,9)
for i in range(0,9):
if Murderer == i:
#print Suspect_ID if working
print(Suspect_ID[i])
First of all your method readinSuspects() does not take parameters, but you invoke it with one argument - Suspect_ID which is not defined yet.
I have reworked your code so now it must work:
import random
#Global variable
Suspect_name = []
Suspect_age = []
Suspect_motive = []
Suspect_ID = []
IsMurderer = []
Guesses=[0]
Murderer=[0]
#Read In Function
def readinSuspects():
#local variables
global Suspect_name
Suspect_name=["","","","","","","","","",""]
global Suspect_age
Suspect_age=[0,0,0,0,0,0,0,0,0,0]
global Suspect_motive
Suspect_motive=["","","","","","","","","",""]
global Suspect_ID
Suspect_ID=[0,0,0,0,0,0,0,0,0,0]
global IsMurderer
IsMurderer=[False,False,False,False,False,False,False,False,False,False]
#subprogram body
file = open("suspects.txt","r")
for i in range(0,9):
Suspect_name[i],Suspect_age[i],Suspect_motive[i], Suspect_ID[i]=file.readline().split(',')
return Suspect_name,Suspect_age,Suspect_motive,Suspect_ID,IsMurderer
#randomly assign murderer
readinSuspects()
Murderer = random.randint(0,9)
for i in range(0,9):
if Murderer == i:
#print Suspect_ID if working
print(Suspect_ID[i])
Also read about if __name__ == '__main__': - it is a good python practice, but without it it still works. And here you can read how to define global vars in python How to define global variables in python SO
Your code has much more to be discussed, but I will leave your teacher to do it ;)

Python threads and global vars

Say I have the following function in a module called "firstModule.py":
def calculate():
# addCount value here should be used from the mainModule
a=random.randint(0,5) + addCount
Now I have a different module called "secondModule.py":
def calculate():
# addCount value here too should be used from the mainModule
a=random.randint(10,20) + addCount
I am running a module called "mainModule.py" which has the following (notice the global "addCount" var):
import firstModule
import secondModule
addCount=0
Class MyThread(Thread):
def __init__(self,name):
Thread.__init__(self)
self.name=name
def run(self):
global addCount
if self.name=="firstModule":
firstModule.calculate()
if self.name=="secondModule":
secondModule.calculate()
def main():
the1=MyThread("firstModule");
the2=MyThread("secondModule");
the1.start()
the2.start()
the1.join()
the2.join()
# This part doesn't work:
print firstModule.a
print secondModule.a
Basically I want the "addCount" value in both modules to be the one from "mainModule". After that, when the threads are finished, I want to print the value
of "a" in both of them. The example above doesn't work. I was wondering how can I fix it.
Pass 'addCount' to the function 'calculate', return the value of 'a' in 'calculate', and assign it to a new attribute in MyThread instance.
def calculate(addCount):
a = random.randint(0, 5) + addCount
return a
Modules in python are singletons, so you can put your global variables in module globalModule.py and have both firstModule, secondModule, and mainModule import globalModule and they will all access the same addCount.
However, in general it's a bad practice for threads to have a global state.
This will never work:
print firstModule.a
print secondModule.a
because in here:
def calculate():
# addCount value here should be used from the mainModule
a=random.randint(0,5) + addCount
a is a local variable to the function calculate.
If you really want to write a as a module-level variable, add global declaration:
def calculate():
# addCount value here should be used from the mainModule
global a
a=random.randint(0,5) + addCount

Categories

Resources