This may be a newb thing... but, global variables - python

Ok! Basically, I have a variable being declared in one function, and I would like to use that variable in another function. I do not want to pass parameters, because I feel like there would be a simpler way to do this. This is my code:
#!/usr/bin/python
#import os
import time
print ("Hello and welcome to Pygame!")
time.sleep(1)
print ("Would you like to load? (\"Y/N\")")
def LON():
loadOrNew = raw_input()
if loadOrNew == "N":
hp = 100
strhp = str(hp)
lvl = 1
strlvl = str(lvl)
atk = 5
stratk = str(atk)
defn = 2
strdefn = str(defn)
fout = open("pygame.dat", "w")
fout.write (strhp)
fout.write("\n")
fout.write(strlvl)
fout.write("\n")
fout.write(stratk)
fout.write("\n")
fout.write(strdefn)
fout.close()
FIRSTPLAY()
return
if loadOrNew == "Y":
fin = open("pygame.dat", "r")
hpstr = fin.readline()
lvlstr = fin.readline()
atkstr = fin.readline()
defstr = fin.readline()
hp = int(float(hpstr))
lvl = int(float(lvlstr))
atk = int(float(atkstr))
defn = int(float(defnstr))
fin.close()
return
if loadOrNew != "Y" and loadOrNew != "N":
print("Im sorry, what?")
LON()
return
return
def SAVE():
fout = open("pygame.dat", "w")
fout.write(hp)
fout.write(lvl)
fout.write(atk)
fout.close(defn)
return
def FIRSTPLAY():
print("man/woman?")
gender = raw_input()
if gender != "man" and gender != "woman":
print("Not valid gender.")
FIRSTPLAY()
print("KING - ")
print(" Young " + gender + ", you are herby my knight!")
time.sleep(1)
print(" My daughter, princess PYTHON, has been captured!")
time.sleep(1)
print(" You are to find her, and relieve this world of her captor!")
time.sleep(1)
print(" Some say this evil man's name is GAMEMAKER, but we really don't know.")
time.sleep(1)
print(" What do you think it is?")
captor = raw_input()
time.sleep(1)
print(" So you think it is " + captor + "?")
time.sleep(1)
print(" Very well, find " + captor + " ASAP!")
PLAY()
return
def PLAY():
print hp
print lvl
print atk
print defn
greenSlime(hp, lvl, atk, defn)
return
def greenSlime(php, plvl, patk, pdefn):
MHP = 10
MLVL = 1
MATK = 2
MDEF = 2
print "Green Slime - "
print " HP: 10"
print " LVL: 1"
print " ATK: 2"
print " DEF: 2"
print "ATK OR DEF?"
LON()
I would like to use hp, lvl, atk, and defn variables that were declared in the LON function, in the PLAY function. I'm sure there is a simpler way then passing parameters.

Just declaring a variable inside global will not work. The global keyword is to ask the interpreter not to treat something as a local (overriding a global variable with the same name) when assigning a value to it. What you need to do is define the variable at a scope above the functions which are supposed to share it. Note that you don't need to declare a variable global in function for read-only access. When the interpreter does not find the variable in local scope it automatically looks for it at outer scope. But in case of assignment statement, it creates a new local variable.
So what you want to do is :
hp = None
lvl = None
atk = None
defn = None
def LON():
global hp, lvl, atk, defn
# rest of LON
# rest of the functions
But I should warn you that globals are bad programming practice and passing parameters is the right way to do it.

Inside LON(), you can use the global statement:
def LON():
global hp, lvl, atk, defn
Then, assignments to those variables inside LON() will create global variables. Once the global variables are created, you can use them elsewhere (without needing a global statement). Note that anywhere you want to assign a new value to the global variable, you will need a corresponding global statement inside that function.

What you need to do is to move the functions into a python class. That way all functions inside the class can access the variables, without you needing to make them global.
You'd probably structure the code something like this:
#!/usr/bin/python
#import os
import time
print ("Hello and welcome to Pygame!")
time.sleep(1)
print ("Would you like to load? (\"Y/N\")")
class Game:
def InitialiseNewPlayer(self):
self.hp = 100
self.lvl = 1
self.atk = 5
self.defn = 2
def SavePlayer(self):
fout = open("pygame.dat", "w")
fout.write ( str(self.hp) )
fout.write("\n")
fout.write(str(self.lvl) )
fout.write("\n")
fout.write(str(self.atk) )
fout.write("\n")
fout.write(str(self.defn) )
fout.close()
def LoadPlayer(self):
fin = open("pygame.dat", "r")
self.hp = int(float(fin.readline()))
self.lvl = int(float(fin.readline()))
self.atk = int(float(fin.readline()))
self.defn = int(float(fin.readline()))
fin.close()
def LON(self):
while true:
loadOrNew = raw_input()
if loadOrNew == "N":
self.InitialiseNewPlayer()
self.SavePlayer();
self.FIRSTPLAY()
return
if loadOrNew == "Y":
self.LoadPlayer()
return
print("Im sorry, what?")
# Watch out as this is using a different format to the SavePlayer above!
def SAVE(self):
fout = open("pygame.dat", "w")
fout.write(self.hp)
fout.write(self.lvl)
fout.write(self.atk)
fout.close(self.defn)
def FIRSTPLAY(self):
print("man/woman?")
gender = raw_input()
if gender != "man" and gender != "woman":
print("Not valid gender.")
FIRSTPLAY()
print("KING - ")
print(" Young " + gender + ", you are herby my knight!")
time.sleep(1)
print(" My daughter, princess PYTHON, has been captured!")
time.sleep(1)
print(" You are to find her, and relieve this world of her captor!")
time.sleep(1)
print(" Some say this evil man's name is GAMEMAKER, but we really don't know.")
time.sleep(1)
print(" What do you think it is?")
captor = raw_input()
time.sleep(1)
print(" So you think it is " + captor + "?")
time.sleep(1)
print(" Very well, find " + captor + " ASAP!")
self.PLAY()
return
def PLAY(self):
print self.hp
print self.lvl
print self.atk
print self.defn
self.greenSlime()
def greenSlime(self):
MHP = 10
MLVL = 1
MATK = 2
MDEF = 2
print "Green Slime - "
print " HP: 10"
print " LVL: 1"
print " ATK: 2"
print " DEF: 2"
print "ATK OR DEF?"
game = Game()
game.LON()

Related

Python variable inside of function not able to be called

I am making an rpg type thing with python and I made a few functions but I need to call variables that were stated and altered inside of a separate function. How would I be able to call a variable inside a function.
My Code:
import time
def title():
print("Hello Welcome To Elvoria")
time.sleep(1)
print("Choose Your Gender, Name, And Race")
time.sleep(1)
def gnd():
Gender = input("""Male, Female, Or NonBinary?
""")
if Gender == ("Male"):
genderin = 'Male'
elif Gender == ("Female"):
genderin = 'Male'
elif Gender == ("NonBinary"):
genderin = 'Male'
else:
gnd()
def nm():
namein = input("""What Is Your Character's Name?
""")
print("Welcome To Elvoria "+namein+"")
def rac():
print("""The Race Options Are:
Elf-Good With Archery And Light Armor
Kelner-Good With Two Handed Weapons And Heavy Armor
Human-Good With Bows And Stealth
Mageine-Good With Magic And Speed""")
time.sleep(1)
racin = input("""Now Choose A Race
""")
if racin == ("Elf"):
print ("You Are Now A " + genderin + racin +" Named" + namein + "")
elif racin == ("Kelner"):
print ("You Are Now A " + genderin + racin +" Named" + namein + "")
elif racin == ("Human"):
print ("You Are Now A " + genderin + racin +" Named" + namein + "")
elif racin == ("Magein"):
print ("You Are Now A " + genderin + racin +" Named" + namein + "")
else:
print ("You Are Now A " + genderin + racin +" Named" + namein + "")
title()
time.sleep(1)
gnd()
time.sleep(1)
nm()
time.sleep(1)
rac()
And The Error Code:
print ("You Are Now A " + genderin + racin +" Named" + namein + "")
NameError: name 'genderin' is not defined
Change your functions to return the result, and take the values they need as parameters:
def gnd() -> str:
gender = input("""Male, Female, Or NonBinary?
""")
if gender in ("Male", "Female", "NonBinary"):
return gender
return gnd()
def nm() -> str:
name = input("""What Is Your Character's Name?
""")
print(f"Welcome To Elvoria {name}")
return name
def rac(gender: str, name: str) -> str:
print("""The Race Options Are:
Elf-Good With Archery And Light Armor
Kelner-Good With Two Handed Weapons And Heavy Armor
Human-Good With Bows And Stealth
Mageine-Good With Magic And Speed""")
time.sleep(1)
race = input("""Now Choose A Race
""")
print (f"You Are Now A {gender} {race} Named {name}")
return race
When you call them, make sure to assign the values to variables so you can use them again:
title()
time.sleep(1)
gender = gnd()
time.sleep(1)
name = nm()
time.sleep(1)
race = rac(gender, name)
You have 2 options:
You could create a global variable, and define that using the global statement in your function, so you can use the global value afterwards
You could pass a value to the function, and work with it (the better way, using global variables should be avoided)

Variable will not update

Made my very first program for school using a basic calculator program but added a variable, not sure if it should be global or local. It calculates fine, but does not return 'tribble' as a new integer.
tribble = 1
def buy():
x=int(raw_input("How many?"))
return (tribble + x);
def sell():
x=int(raw_input("How many?"))
return (tribble - x);
def breed():
x=int(raw_input("Multiply them by 2"))
return (tribble * x);
def cull():
x=int(raw_input("Kill half your Tribbles"))
return (tribble / x);
print "1: Buy"
print "2: Sell"
print "3: Breed"
print "4: Cull"
print "0: QUIT"
while True:
CHOICE = int(raw_input("What will you do with your Tribbles?"))
if CHOICE == 1:
print "Buying Tribbles"
print buy()
print "You have" + str(tribble) + "Tribbles."
elif CHOICE == 2:
print sell()
print 'Selling Tribbles'
print "You have" + str(tribble) + "Tribbles."
elif CHOICE == 3:
print 'Breeding Tribbles, good luck.'
print breed()
print "You have" + str(tribble) + "Tribbles."
elif CHOICE == 4:
print "You're killing them!!"
print cull()
print "You have" + str(tribble) + "Tribbles."
elif CHOICE == 0:
exit()
Are you trying to update the value of tribble?
Then instead of print buy() you should update your variable by using: tribble = buy()
That way you know the value has been updated into the result from the function buy().
Do the same for other functions as well.
Hope it helps.
You don't update the value of tribbles in your functions and thus every time a function is called tribbles is being treated as 1, it's original value. Instead of returning tribbles * 2, for example, just do tribbles *= 2 and then return tribbles.
Yes 'tribble' does not get updated inside the while loop. Because everytime the function returns updated tribble, you're just printing it.
You may want to update tribble this way:
...
...
tribble= buy()
print tribble
...
....
You never reassign the result of your operation to the tribble. I also recommend that you avoid global variables where possible. For example, I would rewrite your cull function to the following:
def cull(number_of_tribbles):
x=int(raw_input("Kill half your Tribbles"))
return number_of_tribbles / x # No need for the parenthesis or the semicolon
# To use
tribble = cull(tribble)
# No need for explicit str conversion in print
print "You have", tribble, "Tribbles."
As a side note, it is odd that your message is "Kill half your Tribbles" yet you ask the user for input. You should either hard code to return tribbles / 2 or change the message to the user; same goes for breed.
You can also do it this way:
tribble = 1
def buy():
global tribble
x = int(raw_input("How many?"))
tribble = tribble + x;
...
print "1: Buy"
print "2: Sell"
print "3: Breed"
print "4: Cull"
print "0: QUIT"
while True:
CHOICE = int(raw_input("What will you do with your Tribbles?"))
if CHOICE == 1:
print "Buying Tribbles"
print buy()
print "You have " + str(tribble) + " Tribbles."
...
elif CHOICE == 0:
exit()
All other methods should be changed in a similar way.
However, it's recommended to avoid using global variables.

How do you change a variable in a function to then be used in the main code?

I am quite new to Python and I am having some trouble figuring out the following:
import random
import sys
print("Welcome to this Maths quiz.")
playerName = str(input("Please enter your name: "))
playerAge = int(input("Please enter your age: "))
if playerAge < 11:
print("This quiz is not for your age.")
sys.exit(0)
else :
print("Great! Let's begin.\n")
quizQuestions = ["9(3+8)", "7+9*8", "(9+13)(9-5)", "50*25%", "104-4+5*20"]
quizAnswers = ["99", "79", "88", "12.5", "0"]
quizSync = list(zip(quizQuestions, quizAnswers))
random.shuffle(quizSync)
quizQuestions, quizAnswers = zip( * quizSync)
questionNumber = 1
quizScore = 0
def displayQuestion(quizQuestions, quizAnswers, questionNumber, quizScore):
print("Question " + str(questionNumber) + ": " + quizQuestions[questionNumber - 1] + "\n")
questionAnswer = str(input())
if questionAnswer == quizAnswers[questionNumber - 1]:
print("\nCorrect!\n")
quizScore += 1
else :
print("\nIncorrect! The answer is: " + quizAnswers[questionNumber - 1] + "\n")
while questionNumber < 6:
displayQuestion(quizQuestions, quizAnswers, questionNumber, quizScore)
questionNumber += 1
print("You have a total score of: "+str(quizScore))
I would like the variable "quizScore" in the function "displayQuestion" to increase by one if the player gets a question right. However, after the quiz is finished, the print function at the end always prints the score is 0 even if the player gets questions right.
You have to declare it as a global variable inside the function so that it can modify the variable in the global scope
def displayQuestion(quizQuestions, quizAnswers, questionNumber):
global quizScore
...
quizScore += 1
That being said, you should generally avoid global variables if you can and try to redesign your program to either pass the variables along as arguments and return values, or use a class to encapsulate the data.
Although this won't be the shortest answer, which is to use another global variable. It instead will show you how to avoid using global variables (which are considered harmful) by using Object Oriented Programming (OOP). To accomplish this, most of the code in your question can be encapsulated into a single class named MathQuiz below.
Besides getting rid of almost all global variables, it also provides a usable template for you to create any number of independent math quizzes.
import random
import sys
class MathQuiz:
def __init__(self, questions, answers):
quizSync = list(zip(questions, answers))
random.shuffle(quizSync)
self.quizQuestions, self.quizAnswers = zip(*quizSync)
self.quizScore = 0
print("Welcome to this Maths quiz.")
self.playerName = str(input("Please enter your name: "))
self.playerAge = int(input("Please enter your age: "))
if self.playerAge > 10:
print("Great! Let's begin.\n")
else :
print("This quiz is not for your age.")
sys.exit(0)
def run(self):
for questionNumber in range(len(self.quizQuestions)):
self._displayQuestion(questionNumber)
print("You have a total score of: " + str(self.quizScore))
def _displayQuestion(self, questionNumber):
print("Question " + str(questionNumber) + ": "
+ self.quizQuestions[questionNumber-1]
+ "\n")
questionAnswer = str(input())
if questionAnswer == self.quizAnswers[questionNumber-1]:
print("\nCorrect!\n")
self.quizScore += 1
else :
print("\nIncorrect! The answer is: "
+ self.quizAnswers[questionNumber-1]
+ "\n")
quiz = MathQuiz(["9(3+8)", "7+9*8", "(9+13)(9-5)", "50*25%", "104-4+5*20"],
["99", "79", "88", "12.5", "0"])
quiz.run()

UnboundLocalError: local variable 'Ehealth' referenced before assignment [duplicate]

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 7 years ago.
I'm half way through a chance fighting program and I wanted to shorten my work by using functions. But I got the error,
UnboundLocalError: local variable 'Ehealth' referenced before assignment
This is my code so far...
import random
import sys
import time
print ("You encounter a wild boar.")
time.sleep(1)
Weapon = input("Do you use a 'Bow and Arrow' or a 'Sword'.")
Ehealth = (100)
health = (100)
Ealive = (1)
alive = (1)
def attack():
damage = (random.randrange(5,21))
time.sleep(3)
print ("You attack the Boar for " + str(damage) + " attack points.")
time.sleep(3)
Ehealth = (Ehealth - damage)
print ("The Boars health is at " + str(Ehealth) + ".")
time.sleep(3)
if Weapon == ("Bow and Arrow"):
Emiss = (20) #out of 40
miss = (15) #out of 40
Espeed = (random.randrange(1,11))
speed = (random.randrange(1,11))
if Espeed > (speed):
print ("The Boar is faster than you so he attacks first.")
time.sleep(3)
print ("Your health is at " + str(health) + " and the Boars health is at " + str(Ehealth) + ".")
time.sleep(3)
while (alive == 1): #1 = alive, 2 = dead
Emiss = (random.randrange(1,41))
if Emiss < (20):
print ("The Boar missed.")
attack()
if Ehealth > (0):
alive = (1)
continue
else:
alive = (2)
print ("You Won!")
sys.exit()
Edamage = (random.randrange(5,16))
print ("The Boar attacks you with " + str(Edamage) + " attack points.")
time.sleep(4)
health = (health - Edamage)
time.sleep(4)
print ("Your health is at " + str(health) + ".")
time.sleep(4)
if alive <= (0):
print ("You died...")
sys.exit()
attack()
if Ehealth > (0):
alive = (1)
else:
alive = (2)
print ("You Won!")
sys.exit()
I got the error at the line on
Ehealth = (Ehealth - damage)
Any help would be appreciated.
You are trying to use the variable that lies outside of the function. In any case I'd do this:
def attack():
global Ehealth
damage = (random.randrange(5,21))
time.sleep(3)
print ("You attack the Boar for " + str(damage) + " attack points.")
time.sleep(3)
Ehealth = (Ehealth - damage)
print ("The Boars health is at " + str(Ehealth) + ".")
time.sleep(3)
Do note the 'global' keyword is needed if you're changing the value of the variable.
You are assigning to that variable in the attack() function:
Ehealth = (Ehealth - damage)
Assignment in a function makes a name local; you appear to expect it to be a global instead. Because it is a local, and hasn't been assigned to in the function before that line, you get your error.
Tell Python to treat it as a global instead. Add this line to your function (as the first line is probably a good idea):
global Ehealth
This tells the Python compiler to treat Ehealth as a global within your function, even though you assign to it.
Ehealth is global variable, If you just print it then there wont be any error But when you try to modify it, function consider it as local variable.
Solution :-
def attack(Ehealth=Ehealth):

Issues with global variables and their values

I'm having some issues with this code. There is a lot of other code to go with it but none that will interfere or have any affect on the issue I'm having. So basically, when I run the code and we get to the for loop at the bottom, it prints nothing because apparently the variable 'walls' = 0, even though I've already given it a valid input. If anyone could help it would be much appreciated.
global walls
global wallLengths
walls = 0
wall = 0
wallLengths = 0
def clientDetails():
#global walls
print("Welcome to the InHouse Solutions Room Painting Price Calculator")
print("STEP 1 - CLIENT DETAILS")
print("Please enter your full name")
userName = input(">>>")
print("Please enter your post code")
postCode = input(">>>")
print("Please enter you first address line here:")
addressLineOne = input(">>>")
print("Please enter your second address line here (OPTIONAL)")
addressLineTwo = input(">>>")
print("Thank you for your information")
print (userName)
print (addressLineOne + ", " + addressLineTwo + ", " + postCode)
print (" ")
def ValidationOne():
print ("Is this information correct? Pleast enter Yes or No")
clientDetailsCorrect = input(">>>")
if clientDetailsCorrect == "no" or clientDetailsCorrect == "No":
clientDetails()
elif clientDetailsCorrect == "Yes" or clientDetailsCorrect == "yes":
roomDimensions()
else:
("Invalid response, please try again")
ValidationOne()
ValidationOne()
def roomDimensions():
global walls
print ("STEP 2 - ROOM DIMENSIONS")
def ValidationTwo():
global walls
print ("How many walls does your room have?")
walls = int(input(">>>"))
if walls > 10 or walls < 3:
print("Invalid, please enter a number between 3 and 10")
ValidationTwo()
elif walls == " " or walls == "":
print("Invalid")
ValidationTwo()
def ValidationThree():
global walls
print ("How tall is the room in meters?")
roomHeight = float(input(">>>"))
if roomHeight < 2.4 or roomHeight > 6:
print ("Invalid, please enter a value between 2.4 and 6")
ValidationThree()
def IndividualWalls():
global wallLengths
global walls
for i in range(1,walls):
print("Please enter the width of wall" , i)
wallLengths[i] = float(input(">>>"))
ValidationTwo()
ValidationThree()
IndividualWalls()
clientDetails()
there is no need to use 'global' keyword when declaring a global at the top of the script:
>>> walls = 0
>>> def increase_walls():
... global walls
... walls += 1
... print walls
...
>>> increase_walls()
1
I can't comment to your question because I don't have over 50 reputation so I will ask here
Can you tell me what the function roomDimensions does?
I tried to run it and you have some deep recursion problem (you can't call recursion function without any if - it will run forever) BUT the first thing that I notice is that you don’t initialize the walls variable so it will not be global variable it will be non-local variable. and you don't call any inner function ( ValidationTwo, ValidationThree,IndividualWalls)
so you main problems are: (handle them in this order)
walls initialize
you didn't call any inner function
deep recursion
here is my example for the use of the three of above:
global_var = 12
def outer():
global global_var
print("*"*10)
print('hello im outer function')
print("*"*10)
def inner1():
global global_var
print('hello im inner1 function')
if global_var < 10:
return 'end for inner1'
print ('global_var is: ' + str(global_var))
global_var -= 1
return inner1()
def inner2():
global global_var
print('hello im inner2 function')
if global_var >= 10:
return 'end for inner1'
print ('global_var is: ' + str(global_var))
global_var += 1
return inner2()
if global_var >= 10:
return inner1()
else:
return inner2()
if __name__ == '__main__':
print outer()

Categories

Resources