This question already has answers here:
Using global variables in a function
(25 answers)
Closed 3 years ago.
I am trying to change a variable further down the program. I have a global variable declared at the start of the program and I want to change the variable in different functions down the program. I can do this by declaring the variable inside the function again but I would like to know is there a better way of doing this. Some test code is below to explain what I mean.
ID = 'No'
project = ("Yep"+ID) # ID added with 'No' value which I later want to change
def pro():
ID = "YES"
print ID
def pro1(ID):
# I could declare project again to get this to work, but I would like to avoid this
print project # I want this to print with the new ID number.
if __name__ == '__main__':
pro()
pro1(ID)
Has anyone any ideas, thanks
I have tried the global variable but when I do this the project variable still prints out YepNo instead of YepYES. I want the new variable from the function proto change the variable in the project variable.
To update global variables you could use
global ID
ID="Yes"
before assigning variable to ID = "YES"
But changing ID will be no effect on project variable, project = ("Yep"+ID), because project is already a string
you need to make a function like
def getprojectname(ID):
return project+ID
The whole program may be like this
UPDATE:
... removed
Beware, you're doing it wrong multiple times.
Even though you could use the global statement to change a global (it is discouraged since it's better to use function parameters and return values), that would NOT change other already assigned values. E.g. even though you reassign ID, you would NOT reassign project. Also: your functions return nothing, there's no point in assigning a name to their return value, and it's a BAD habit using an all-uppercase name (ID) for a variable since it's a convention to use them for constants.
This should clarify you the way global works:
myid = ''
project = ("Yep"+myid) #ID added with no value which I later want to change
def mutate_id():
global myid
myid = "YES"
def mutate_project():
global project
project = ("YEP" + myid)
if __name__ == '__main__':
print "myid", myid
print "project ", project
print
mutate_id()
print "myid", myid
print "project ", project
print
mutate_project()
print "myid", myid
print "project ", project
print
But the best way is to do WITHOUT globals:
def get_new_id(old):
return "YES"
def get_new_project(old):
return ("YEP" + myid)
if __name__ == '__main__':
myid = ''
project = ("Yep"+myid)
print "myid", myid
print "project ", project
print
myid = get_new_id(myid)
print "myid", myid
print "project ", project
print
project = get_new_project(project)
print "myid", myid
print "project ", project
print
This will make all code interaction clear, and prevent issues related to global state change.
Use the global statement.
The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals.
Example: http://www.rexx.com/~dkuhlman/python_101/python_101.html#SECTION004340000000000000000
P.S.
But don't use global too often, see http://www.youtube.com/watch?v=E_kZDvwofHY#t=10m45
In your code you have two problems. The first about changing ID variable, which could be solved by using global.
The second that your code calculate project string and after that project don't know about ID.
To avoid code duplication you can define function to calc project.
So we have:
ID = 'No'
def GetProject():
return "Yep"+ID
def pro():
global ID
ID = "YES"
print ID
print GetProject()
pro()
print GetProject()
You can mutate without reassigning:
variables = {}
def pro():
if variables['ID'] == '':
variables['ID'] = 'default'
Why not use a dictionary?
>>> attr = {'start':'XXX', 'myid':'No'}
>>>
>>> def update_and_show(D, value = None):
... if value: D['myid'] = value
... print D['start'] + ' ' + D['myid']
...
>>> update_and_show(attr)
XXX No
>>> update_and_show(attr, 'Yes')
XXX Yes
>>> update_and_show(attr, 'No')
XXX No
>>>
Related
Hi guys hope u are doing well, i'm new with python :)
so i have two issues the first how can i use the variable name from the init to my function game() which it use two args (those args whose make it realy difficult for me !) as u can see in code bellow:
# FUNCTION.py
class penGame():
def __init__(self):
print("Welcome to Pendu Game")
self.name = input("Enter your name: ") # IMPORT THIS VARIABLE FROM HERE
def game(self, letter, rword):
letter = letter.lower()
if letter in rword:
for Id, Value in enumerate(rword):
if Value == letter:
donnee.default_liste[Id] = letter
else:
name2 = self.name # it deosn't work i got 1 missing arg when i run the code from MAIN.py
print(f"try again {name} it's wrong ")
print("-".join(donnee.default_liste))
The second issue is i need to use the same variable (name) from init in another module which is my main module and i couldn't use it cause i tried to create an object from class penGame() like:
myObject = penGame()
name2 = myObject.name
then use the name2 inside of the if condition as u can see bellow but it doesn't work properly cause it run the init again which is not what i want actualy !
any idea how can i did it plz?
#MAIN.py
import donnee
from fonctions import penGame
random_word = random.choice(donnee.liste_words) # creation of random word from liste_words
penGame() #call the constructor
while donnee.counter < donnee.score:
letter = input("Enter the letter: ")
if penGame.check(letter):
print("You cant use more one letter or numbers, try again !")
else:
penGame.game(letter, random_word) # as u can see that's the reason cause i supposed to send 3 args instead of two ! but i only need those two !!?
if penGame.check_liste():
myObject = penGame() # that's cause runing the init everytime !!
name2 = myObject.name
print(f"congratulation {name2} you've guessed the word, your score is: {donnee.choice-donnee.counter} point.")
break
if penGame.loser():
print(f"the word was {random_word.upper()} you have done your chances good luck next time.")
donnee.counter += 1
Thank u in advance hope u help me with that and excuse my english if it wasn't that good :) :)
1.Error
You're calling the methods on the class penGame, not on a instance of penGame.
This causes your missing argument error because the method needs an instance of the class (the self parameter) but don't get one.
Instead use your variable (from the second solution):
if mygame.check(letter):
print("You cant use more one letter or numbers, try again !")
else:
mygame.game(letter, random_word)
...
Replace penGame with mygame also in the other calls.
Error
Save the result of the call in a variable and you won't need to recreate it.
mygame = penGame() # call the constructor
This line can then be removed:
myObject = penGame() # that causes the init to run again because it creates a new instance!
Id, conf = recognizer.predict(gray[y:y+h,x:x+w]
def hour(cn):
for z in range(9,17):
if now.hour == z:
worksheet(cn, str(z)+":00")
def identify(number):
sht = gc.open("Test")
wks3 = sht.worksheet("NAMES")
b = wks3.acell('B'+str(number)).value
a = wks3.acell('A'+str(number)).value
if(Id == a and conf<65):
print(Id, conf)
Id = str(b)
Time = time.ctime()
hour(number)
elif(conf>64):
print(conf)
Id = "Unknown"
for m in range(2,100):
identify(m)
The above code is being used for facial recognition, I copied what I felt was necessary, it is not the entire code.
I'm trying create a function which I want to call back in a for loop
What am I doing wrong? I've been looking t this for 6 hours now, and anything I try doesn't seem to work.
I get a message back saying "UnboundLocalError: local variable 'Id' referenced before assignment"
It's impossible because I'm assigning with:
a = wks3.acell('A'+str(number)).value
So it grabs the ID number from the google spread sheet and checks if it is equaled to that, can someone tell me where I'm going wrong here?
def identify(number):
sht = gc.open("Test")
wks3 = sht.worksheet("NAMES")
b = wks3.acell('B'+str(number)).value
a = wks3.acell('A'+str(number)).value
#because you did, Id = ?
if(Id == a and conf<65):
print(Id, conf)
Id = str(b)
Time = time.ctime()
hour(number)
elif(conf>64):
print(conf)
Id = "Unknown"
Because you did, variable Id isn't passed as any parameter or global/local variable or as an argument to existing class.
If Id was parameter:
def identify(number,Id):
If Id was global variable:
def identify(number):
global Id
If Id was local variable:
def identify(number):
id = None # or some other data type
And if Id was argument from some class:
some_class.Id
In short you referenced Id before it was initialised. This is rookie mistake and there is some stuff where you can actually init a variable in if elif else statement but you need to trow a none of above logic of the rule.
if True: Id = 2; elif False: Id = 3; else: Id =0 #this is pseudocode, don't paste it in.
Also have in mind that next variable is also Unbound conf
EDIT:
Often to avoid this problem we write code like this:
def somefunction(parm1,parm2... ):
# global variables : description for variable stack is optional
global var1,var2 # if needed
#local variables
var3,var4 = None;
var5 = 'something else'
#in body functions : functions inside functions or just general program functions
def a(... ): return ...
#body : actually what function/program does.
# returning , finishing statement.
When I run this it works, but it says
"name 'select_place' is assigned to before global declaration"
When I get rid of the second global, no comment appears, but as select_place is no longer global it is not readable (if selected) in my last line of code.
I'm really new to python, ideally I'd like a way of not using the global command but after searching i still can't find anything that helps.
My code:
def attempt(x):
if location =='a':
global select_place
select_place = 0
if location =='b'
global select_place
select_place = 1
place = ([a,b,c,d])
This is the start of some turtle graphics
def Draw_piece_a(Top_right):
goto(place[select_place])
You need to declare the variable first, additionally the function code can be made clearer:
select_place = False
def attempt(x):
global select_place
if location == 'a':
select_place = 0
elif location == 'b':
select_place = 1
Also, there is no return value for attempt(), is this what you want?
Just started learning python (3.2) and have a question. I have created a some code that creates some stats (as in health, magic etc etc) and the numbers are randomly generated. Here is the code...
def stats ():
print ()
print ('Some text.')
done = False
while not done :
charname = input(str('What is the name of the character? '))
hp = random.randint(5,20)
mp = random.randint(4,20)
stre = random.randint(3,20)
agi = random.randint(3,20)
spd = random.randint(3,20)
wis = random.randint(3,20)
intel = random.randint(3,20)
cha = random.randint(3,20)
print (charname)
print ('HP:',hp)
print ('Mana:',mp)
print ('Strength:',stre)
print ('Agility:',agi)
print ('Speed:',spd)
print ('Wisdom:',wis)
print ('Intelligence:',intel)
print ('Charisma:',cha)
print ()
done = input('All done? yes/no ')
if( done == 'yes' ):
done = True
elif(done == 'no'):
done = False
while done :
print ()
print ('Now that your stats are done, you can go on your adventure!')
done = False
Now this works fine, but how could I call on this function again in case I wanted to view the stats again with it keeping the same stats it randomly generated before?
Sorry if the question is bit off. Still all new to programming.
Thank you.
Since you're new to programming, here's some advice on a different way to store your data (without actually coding it for you).
First, define a Character class, with attributes for HP, mana, etc. I don't know if you know about classes yet, but here's an intro. There are various tricks you can do to get around having to explicitly write in the names for HP, mana, etc, but for learning's sake, it's probably better to do them all manually for now.
Then def a random_character() function that creates a Character object with random attributes, defined like how you're doing now, but instead of saving them in different variables that Python doesn't know have anything to do with one another, puts them in a single Character.
Add a __str__ method to the Character class, so that if char is a Character, print(char) prints out the attributes.
If you want to be able to keep track of characters, use pickle to store it in files.
If you have questions about any part of this, just ask. :)
Your function now uses local variables to record the stats you've generated. You'll need to bundle them together into either a dictionary or an object so that you can pass them around as a value.
For example:
def get_stats():
stats = {}
stats['charname'] = input(str('What is the name of the character? '))
stats['hp'] = random.randint(5,20)
stats['mp'] = random.randint(4,20)
stats['stre'] = random.randint(3,20)
stats['agi'] = random.randint(3,20)
stats['spd'] = random.randint(3,20)
stats['wis'] = random.randint(3,20)
stats['intel'] = random.randint(3,20)
stats['cha'] = random.randint(3,20)
return stats
def print_stats(stats):
print (stats['charname'])
print ('HP:',stats['hp'])
print ('Mana:',stats['mp'])
print ('Strength:',stats['stre'])
print ('Agility:',stats['agi'])
print ('Speed:',stats['spd'])
print ('Wisdom:',stats['wis'])
print ('Intelligence:',stats['intel'])
print ('Charisma:',stats['cha'])
print ()
you can use def keyword to declare functions . Def
def stat():
you can call the function like this in your desired location. stat()
If you want easy storage in an external file, you can use the pickle module, and a dictionary of the values you wish to store.
for example:
import pickle
stats={}
stats['hp'] = random.randint(5,20)
stats['mp'] = random.randint(4,20)
stats['stre'] = random.randint(3,20)
stats['agi'] = random.randint(3,20)
stats['spd'] = random.randint(3,20)
stats['wis'] = random.randint(3,20)
stats['intel'] = random.randint(3,20)
stats['cha'] = random.randint(3,20)
#save the stats into the file by using:
pickle.dump(stats,yourstatfile.pkl)
#then to load it again from any program just use:
stats=pickle.load(yourstatfile.pkl) #you assign it to a variable, so if i used the variable 'lol' i would use it as lol['hp'] not stats['hp'] like it was originally used when saving.
#then you can use it just like any other dictionary:
print "your hp: "+str(stats['hp'])
I wrote the below code in order to check for three files and whichever files exist, run a "scan" on the file (if a file does not exist, don't worry about it just run a "scan" on the available files) and produce the proper output file on those available files.
The program I'm working on includes the following code:
def InputScanAnswer():
scan_number = raw_input("Enter Scan Type number: ")
return scan_number
This function checks if these three files exist and if so, assign specific values to hashcolumn and to filepathNum
def chkifexists():
list = ['file1.csv', 'file2.csv', 'file3.csv']
for filename in list:
if os.path.isfile(filename):
if filename == "file1.csv":
hashcolumn = 7
filepathNum = 5
if filename == "file2.csv":
hashcolumn = 15
filepathNum = 5
if filename == "file3.csv":
hashcolumn = 1
filepathNum = 0
#print filename, hashcolumn, filepathNum
def ScanChoice(scan_number):
if scan_number == "1":
chkifexists()
onlinescan(filename, filename + "_Online_Scan_Results.csv", hashcolumn, filepathNum) #this is what is giving me errors...
elif scan_number == "2":
print "this is scan #2"
elif scan_number =="3":
print "this is scan #3"
else:
print "Oops! Invalid selection. Please try again."
def onlinescan(FileToScan, ResultsFile, hashcolumn, filepathNum):
# web scraping stuff is done in this function
The error that I run into is global name 'filename' is not defined.
I realize that the problem is I'm attempting to send local variables from chkifexists() to the onlinescan() parameters. I tried using
return filename
return hashcolumn
return filepathNum
at the end of the chkifexists() function but that was not working either. Is there anyway to do what I'm trying to do in the
onlinescan(filename, filename + "_Online_Scan_Results.csv", hashcolumn, filepathNum)
line without using global variables? I know they are discouraged and I'm hoping I can go about it another way. Also, does having hashcolumn and filepathNum parameters in onlinescan() have anything to do with this?
Inside chkifexists, you would return all three variables like so:
return (filename, hashcolumn, filepathNum)
You would retrieve these by calling the function like so:
(filename, hashcolumn, filepathNum) = chkifexists()
You now have them in your function scope without needing global variables!
Technically, you don't need the parenthesis, either. In fact, I'm not sure why I included them. But it works either way, so what the heck.