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

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):

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)

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()

Python function not calling when called w/out error

So I'm programming a text-based video game for a lark and one of the situations is if enemy health is less than 1 than it does a whole bunch of things (Mostly modifying variables and printing lines) then it should call a function. Problem being it's not calling. The function is being read and checked against the defined function, but it's not executing. Any idea what I'm doing wrong?
if enemy_hull < 1:
print (enemy_name + " breaks up as explosions rack the hull! You've won!")
scrap = scrap + randint(27,67)
scrapStr = str(scrap)
missile_count = missile_count + randint(1,8)
missile_countStr = str(missile_count)
shields = 60
shieldsStr = str(shields)
print ()
print ()
print("Your ship has " + shieldsStr + " shields and " + hullStr + " Hull Strength. You have " + scrapStr + " scrap and " + missile_countStr + " missiles.")
time.sleep(3)
FTLJump()
That's the function in question at the end, FTLJump, and it's being read but not executed. https://repl.it/Blt4/98 is the full code if anyone wants to take a looksie. Thanks!
Your FTLJump function only declares global variables and exits: there is no code inside. There is an indentation issue in that function.

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()

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

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()

Categories

Resources