Was playing with loops to prepare for my incoming project. and I found infinite loop when using while loop + main function
#1
def choice(name):
while True:
if name == "Eat"
print("I don't want to eat now")
elif name == "Drink"
print("NOPE")
else:
print("o.O?")
def main():
name = input("Eat or Drink ? :")
choice(name)
main()
#2
while True:
name = input("Eat or Drink ? :")
if name == "Eat"
print("I don't want to eat now")
elif name == "Drink"
print("NOPE")
else:
print("o.O?")
Number 2 doesn't generate infinite loops despite I don't have any return
But when I use Number 1, so that I can use the name variable into different functions in future, it generates infinite loop.
Can I know the reason why it is happening? and how do I fix it while keeping name variable nested in main function?
Thanks!
It's because in version #2 you read input from console on every loop iteration (this line: name = input("Eat or Drink ? :")). So it is still an infinite loop, but this time it waits on every iteration until you provide some input.
You can fix it by just adding this line: name = input("Eat or Drink ? :") to your choice function or use:
for i in range(100):
...
If you want to limit the number of iterations.
EDIT:
Ok, so take while True from choice function and put it into main, like this:
def main():
while True:
name = input("Eat or Drink ? :")
choice(name)
... other functions using name
Related
I am new to Python. I am trying to run the following code. But every time I try to run it, the IDE says that the break is outside the loop
catname = []
print("Enter the name of the cats")
name = input()
if name == '':
break
catname = catname+[name]
print("The cat Names are :")
for catname in name:
print(name)
Can you please help me?
Thanks
You use break when you want to break free from a loop, to exit the loop, to jump to the nearest code after the loop.
Your code doesn't contain a loop, so nothing to break free from, hence the error.
I think you meant exit() instead of break
You use "break" just inside the loop ("for" or "while"), you are trying use brake inside the "if"
How about this:
if name != '':
catname = catname+[name]
print("The cat Names are :")
for catname in name:
print(name)
Your break statement is not in a loop, it's just inside an if statement.
But maybe you want to do something like the following.
If you want to let the user enter an random number of names and print the names out, when the user entered nothing, you can do the following:
# Here we declare the list in which we want to save the names
catnames = []
# start endless loop
while True:
# get the input (choose the line which fits your Python version)
# comment out the other or delete it
name = input("Enter the name of a cat\n") # input is for Python 3
# name = raw_input("Enter the name of a cat\n") # raw_input is for Python 2
# break loop if name is a empty string
if name == '':
break
# append name to the list catnames
catnames.append(name)
print("The cat names are :")
# print the names
for name in catnames:
print(name)
What you are looking for is exit().
However, your code has also other problems, here is a piece of code that does what you probably want (when prompted, enter the names separated by spaces, like: Cat1 Cat2):
name = raw_input("Enter the name of the cats: ")
if len(name) == 0:
exit()
print("\nThe cat Names are:")
for c_name in name.split():
print(c_name)
If this is the entirety of your code, then it's telling you exactly what the problem is:
catname = []
print("Enter the name of the cats")
name = input()
if name == '':
break
You have a break statement in the code that's not contained inside a loop. What do you expect the code above to do?
I am making a text-based game on python using the class system to keep track of main character changes (like its name). I am writing the main code for the game outside of the Main Character Class- inside of the main function.
I am struggling because I need to update self.character_name inside the Main Character class to an input from the user inside the main function. I am unsure how to do this, I have the code written below- however it is not updating the name inside Main Character class. How can I rewrite this?
I'm also worried that I will have this problem when trying to update pets, characters_known. However, I do not seem to have this problem with updating Health or XP....
class Main_Character():
def __init__(self):
self.health=100
self.exp=0
self.level=0
self.character_name=""
self.characters_known={None}
self.pets={None}
self.progression_tracker=0
def __str__(self):
return "Name: "+ str(self.character_name)+" | "+ "Health:"+ str(self.health) + " | " +"XP:"+ str(self.exp) + " | "+ "Level:"+ str(self.level)+" | "+"Pets:"+str(self.pets)
def Char_Name(self,name):
if name.isalpha()==False:
print("You entered a name containing non-alphabetic characters, pease reenter a new name:")
main()
elif len(name)>=10:
print("You entered a name containing 10 or more characters, pease reenter a new name:")
main()
else:
self.character_name=name
def Char_Level_Experience(self,exp,b):
self.exp+=exp
b=2
if exp<=0:
exp=1
ans = 1
level=0
while ans<exp:
ans *= b
level += 1
if ans == exp:
self.level=level
print("You have reached level", self.level)
else:
level = int(log(exp, 2))
level = min(level, exp)
if level>=0:
self.level=level
else:
level=0
def healing(self,heal):
if self.health+heal>=100:
self.health=100
else:
self.health+=heal
def other_answers(answer):
if answer=='quit':
raise SystemExit
if answer=='pets':
print("Pets owned:", Main_Character().pets)
user_decision=input("Would you like to continue where you left off? Type 'yes' to continue, or 'no' to go back to main menu")
if user_decision=='yes':
if Main_Character().progression_tracker==0:
main()
elif Main_Character().progression_tracker==1:
choice1()
if user_decision=='no':
main()
else:
other_answers(user_decision)
if answer=='characters':
print("Characters met:", Main_Character().characters_known)
user_decision=input("Would you like to continue where you left off? Type 'yes' to continue, or 'no' to go back to main menu:")
if user_decision=='yes':
if Main_Character().progression_tracker==0:
main()
if Main_Character().progression_tracker==1:
choice1()
if user_decision=='no':
main()
else:
other_answers(user_decision)
def start_check():
print("If you understand the game, type 'go' to continue- if not, type 'more information' to receive more information about how to play the game")
begin_game=input("")
if begin_game=="go":
choice1()
if begin_game=='more information':
print("\n","The object of the game is to gain XP [experience points] without dying")
start_check()
else:
other_answers(begin_game)
def choice1():
Main_Character().progression_tracker=1
print("You are a knight in the Kings Guard- the King has asked to meet with you about a very special mission")
print("What would you like to do?")
print(" 1.Go Directly to King","\n", "2. Finish your dinner")
choice=input("1 or 2?")
if choice=="1":
Main_Character().Char_Level_Experience(1,2)
elif choice=="2":
Main_Character().Char_Level_Experience(.5,2)
else:
other_answers(choice)
print(Main_Character())
def main():
print("Welcome!")
unfiltered_name=input("Please enter the name of your character:")
Main_Character().Char_Name(unfiltered_name)
print("Welcome,", Main_Character().character_name,"!", "Here are your current stats!")
print(Main_Character())
start_check()
You haven't quite understood how classes and instances work.
Calling the class is what you do when you need a new character. Every time you call Main_Character(), you get a whole new instance - with the default values as set in __init__. If you had characters for each of your friends, you would call it one time for each one. You then would need to keep each of those instances in a variable, so you can reference them again each time.
So, for instance:
my_character = Main_Character()
unfiltered_name=input("Please enter the name of your character:")
my_character.Char_Name(unfiltered_name)
print("Welcome,", my_character.character_name,"!", "Here are your current stats!")
print(my_character)
You create a new character each time you call Main_Character. Instead, you should call it once:
the_character = Main_Character()
...
the_character.name = "..."
Newish to python, working on a text adventure, testing out the use of functions.
def cell1():
loop = 1
while loop == 1:
print("ONE")
cave1 = input()
if cave1 == ("end?"):
print("\nthis should end program")
loop = 0
break
elif cave1 == ("TWO"):
global testvar
testvar = 1
option1()
else:
print("INVALID")
def option1():
print("TWO")
loop = 1
while loop == 1:
print("test1 definition")
print (testvar)
test1 = input()
if test1 == ("ONE"):
print("you pick up the cheese")
loop = 0
cell1()
elif test1 == ("THREE"):
option2()
else:
print("INVALID")
def option2():
print("THREE")
loop = 1
while loop == 1:
print("This is option 3")
test2 = input()
if test2 == ("ONE"):
print("testering2")
cell1()
elif test2 == ("TWO"):
global testvar
testvar = 2014
option1()
else:
print("INVALID")
run = True
while run == (True):
print ("testing 123")
cell1()
print("restart about to activate")
cont = input("Restart? ")
if (cont) != "yes":
break
This program should allow you to go between options (what would be rooms) and eventually in cell1, the program should be end-able.
if the program is run and "end?" is typed as the first input, the program goes into the continue bit at the bottom, however, if you go between the 'rooms' then back to cell1, typing "end?" will call option 2.
Ive had a look around and it is still baffling me, am i ding something wrong?
Any help is appreciated, thank you.
The reason "end?" only quits for the player when they are within the first cell is because you're only checking for that input therein. The execution contained within option1() and option2() doesn't affect the execution of cell1(). You're not returning anything from your option functions, nor are you changing a sentinel value.
So, there's two basic ways you could go about this.
First, you could return a value from your functions:
if option1() == "END":
break
Or, you could alter your while loop:
# is_running is defined globally
while is_running:
And then just set is_running to False in any of your methods whenever the user types "end?". That'd probably be the easiest way with the design you're using now.
I'm sure you can tell, though, that in general your program is going to get exponentially more complex as you add more rooms and your function calls get further nested.
I'm pretty sure that the issue you're having is because you don't always break out of the loop in one function when you call another function. For instance, if your entries were TWO, ONE then end?, you'd find yourself still in the cell1 loop. That's because when the inner call to cell1 returns, the control flow of the program goes back to where that function was called from, which is option1, since loop is now 0, the loop ends and option1 returns, to the outer call to cell1, where the loop is still running.
Unless you want the game you're designing to have a tree structure, where you can return to where you came from with different semantics than moving to some other place, I'd suggest using a different architecture. Rather than each of your functions calling the next function when appropriate, return that function instead. Then you'd write a single top level loop that calls the function. Here's an example where the function to be called by the top level loop is saved in a variable named state:
def cell1():
print("In cell1!")
while True:
choice = input("pick 'ONE' or 'TWO' (or type 'quit' to exit):")
if choice == "ONE":
return option1
elif choice == "TWO":
return option2
elif choice == "quit":
return None
else:
print("I'm sorry, I didn't understand that.")
def option1(): # these other two functions are very basic in my example
print("In option1!") # but you can make them as complex as you want
return option2
def option2():
print("in option2!")
return cell1
def control_loop(initial_state=cell1):
state = initial_state
while state is not None:
state = state() # the next state is the return value of the previous state
The problem is you are getting deeper and deeper within nested functions. For example, changing
if test1 == ("ONE"):
print("you pick up the cheese")
loop = 0
cell1()
to
if test1 == ("ONE"):
print("you pick up the cheese")
loop = 0
break
will allow you to run your program, enter room two, go back to room one, and "end?" will work properly. This won't fix your issues completely though because there is a similar problem where when you go from two to three where if you simply changed
if test2 == ("ONE"):
print("testering2")
cell1()
to
if test2 == ("ONE"):
print("testering2")
break
it would break the current function and go back into option1() (if you run your program, go to room two, then to room three, then back to one) where "end?" doesn't do anything. Hopefully this gets you on the right track.
Like I said in my previous question, I'm a python amateur. I've made a couple silly mistakes. I'm attempting to make a highly simple greeting program using Python 3.4 however I have encountered an error. The error I have is:
UnboundLocalError: local variable 'lastNameFunction' referenced before assignment
Here's my code (I know I probably don't need to post it all, but there isn't much of it):
def main():
import time
running = True
while (running):
firstNameInput = input("What is your first name?\n")
firstName = firstNameInput.title()
print ("You have entered '%s' as your first name. Is this correct?"%firstName)
time.sleep (1)
choice = input("Enter 'Y' for Yes or 'N' for No\n")
if(choice.upper() == "Y"):
lastNameFunction()
elif(choice.upper() == "N"):
main()
def lastNameFunction():
lastNameInput = input("Hi %s. Please enter your last name. \n"%firstName)
lastName = lastNameInput.title()
if __name__ == '__main__':
main()
I'd appreciate any help and advice! Please take into consideration I am really new to this stuff. I'm also not quite sure on having a function inside of a function, but I thought it would be a fix so that the 'firstName' was available when entering the 'lastName'.
Thanks in advance! :)
You need to move the lastNameFunction declaration somewhere before you call it using lastNameFunction(), e.g.:
def main():
import time
running = True
while (running):
firstNameInput = input("What is your first name?\n")
firstName = firstNameInput.title()
print ("You have entered '%s' as your first name. Is this correct?" % firstName)
time.sleep (1)
choice = input("Enter 'Y' for Yes or 'N' for No\n")
def lastNameFunction():
lastNameInput = input("Hi %s. Please enter your last name. \n" % firstName)
lastName = lastNameInput.title()
if(choice.upper() == "Y"):
lastNameFunction()
elif(choice.upper() == "N"):
main()
if __name__ == '__main__':
main()
You can also move it outside the main function, but you will then need to pass the firstName in using the function arguments:
def lastNameFunction(firstName):
lastNameInput = input("Hi %s. Please enter your last name. \n" % firstName)
lastName = lastNameInput.title()
def main():
...
lastNameFunction(firstName)
...
Move your lastNameFunction to somewhere before the call. Ideally, you would place this above the main function.
def lastNameFunction():
lastNameInput = input("Hi %s. Please enter your last name. \n"%firstName)
lastName = lastNameInput.title()
def main():
...
The problem is you called lastNameFunction() before you defined it in the while loop. Try defining the function outside the while loop.
The organisation of the whole program seems a little bit off.
Imports usually go at the top of the module.
Functions defined in functions are usually just for closures, which you a) don't need here and b) might be a bit advanced for your current experience level.
Recursive calls like your calling main() from within main() are wrong. When you adopt that style of control flow instead of a loop, you will eventually run into limitations of recursive calls (→ RuntimeError). You already have the necessary loop, so simply leaving out the elif branch already asks the user again for the first name.
running isn't used anywhere, so you can remove it and just use while True:.
I would move asking the user for ”anything” + the question if the input was correct into its own function:
def ask_string(prompt):
while True:
result = input(prompt).title()
print("You have entered '{0}'. Is this correct?".format(result))
choice = input("Enter 'Y' for Yes or 'N' for No\n")
if choice.upper() == 'Y':
return result
def main():
first_name = ask_string('What is your first name?\n')
last_name = ask_string(
'Hi {0}. Please enter your last name.\n'.format(first_name)
)
print(first_name, last_name)
if __name__ == '__main__':
main()
So at school, our teacher asked us to make a program which needs a password to grant access. I have made this however i would like to improve on it by adding a loop count which increase each time it loops round heres what i have so far for the loop count, however it doesn't work.
import time
b=0
a='apple'
def start():
print("enter password")
c=input("-> ")
if c==a:
grant()
else:
delay()
def grant():
end
def delay():
b=b+1
time.sleep(b)
start()
start()
Your problem is inside here:
def delay():
b=b+1
time.sleep(b)
start()
When you do b = b + 1, you're expecting the b variable at the top of the file to increase by 1, right?
You probably haven't learned this yet, but the reason why this doesn't work is because of something called scope.
To fix it, you need to change your delay function to look like this:
def delay():
global b
b=b+1
time.sleep(b)
start()
From looking at your code, I take it you haven't learned how to use while loops yet?
Your solution of repeatedly calling start inside of delay is actually pretty clever. However, if we use a while loop, we can rewrite your program so that it's a little cleaner and more obvious as to what you're trying to do:
import time
password = 'apple'
def start():
counter = 0
user_guess = ''
while user_guess != password:
print("enter password")
user_guess = input("-> ")
if user_guess != password:
counter += + 1 # Same thing as doing `counter = counter + 1`
time.sleep(counter)
grant()
def grant():
print "Access granted!"
start()
Python doesn't recognize b in delay() because it is in global scope.
Try this:
def delay():
global b
b=b+1
time.sleep(b)
start()