0

I’m trying to build a quick little quiz program. I know I’ve got most of it right but when it comes to the code where I ask the user if they have a pet, I’m having a little bit of an issue.

Still pretty new to Python and could really appreciate the help! This small problem is starting to give me quite a headache.

Also, I’m running Python 3.7.1

yes_pets = ["y", "yes", "yeah", "yup", "yeah"]
no_pets = ["n", "no", "nope", "nah", "non"]

name = input("What is your name?: ").strip().capitalize()
age = int(input("How old are you?: ").strip().lower())
place = input("Where do you live?: ").strip().capitalize()
work = input("What do you do for a living?: ").strip().lower()
hobbies = input("What is your favorite hobby?: ").strip().lower()
music = input("Who is your favorite musician?: ").strip().title()
travel = input("What country do you want to visit the most?: ").strip().capitalize()
pets = input("Do you have any pets? (y/n): ").strip().lower()
if pets in yes_pets:
    pets = "your furbaby"
elif pets in no_pets:
    pets = "that $$$"
else:
    for pets in yes_pets or no_pets:
        pets = input("Sorry didn't catch that. Do you have any pets (y/n)?: ").strip().lower()
        if pets in yes_pets:
            pets = "your furbaby"
        elif pets in no_pets:
            pets = "that $$$"

print("\nHi {}! You are {} years old and you live in {}.\nYou work as an {} but you do it for {}.\nWhen you're not working we could probably find you\n{} listening to some {}\ndreaming of going to {} someday.".format(name, age, place, work, pets, hobbies, music, travel))

— I want it to —

Reference the users input of the variable PETS with the acceptable answers in lists yes_pets and no_pets. If the input is in the yes_pets list, I want pets = “your furbaby”. If the input is in the no_pets list I want pets = “that $$$”. However, if the user gives an input that is NOT IN either of those lists, I want it to loop and keep asking that question again until the user gives an acceptable input.

— What I think is happening —

I believe the first if and elif statements work just fine as they work when I give an acceptable input. But when the for loop executes it keeps looping the question even when the user gives an acceptable input. I tried for pets not in yes_pets or no_pets: but that logic doesn’t seem to work. So leaving the NOT out, what I think is happening is that its infinitely looping because the user gave an answer that makes the condition of the loop true? When the user gives another answer that still isn’t in the list it still loops because of the ELSE?

Nikkaih
  • 15
  • 4
  • Your `for pets in yes_pets or no_pets` is actually `for pets in (yes_pets or no_pets)`. Now consider that `p or q` works as `p if p else q`. – Klaus D. Jan 09 '19 at 06:43

7 Answers7

1

Consider using a while loop instead of a for loop. You can have a while True: condition to loop indefinitely, and then break the loop if your condition is satisfied.

while True:
    pets = input("Do you have any pets? (y/n): ").strip().lower()
    if pets in yes_pets or pets in no_pets:
        break
    print("Sorry didn't catch that.", end=' ')
gilch
  • 10,813
  • 1
  • 23
  • 28
  • Why not just loop until your condition is satisfied? – Mad Physicist Jan 09 '19 at 06:53
  • @MadPhysicist Isn't that exactly what I said? It's easier for beginners to think these problems through if they don't feel obligated to only break at the top of the loop. Python doesn't have a do/while like Java. – gilch Jan 09 '19 at 06:58
  • I find that argument specious at best. My downvote was actually not because of that though, since it would, after all, yield a perfectly functional approach. Your answer is quite vague and does not show a sample implementation or detailed walkthrough. – Mad Physicist Jan 09 '19 at 07:02
  • Clever DRY there. +1 – Mad Physicist Jan 09 '19 at 07:15
1

The problem is with the for loop

for pets in yes_pets or no_pets:

try executing the below code..

yes_pets = ["y", "yes", "yeah", "yup", "yeah"]
no_pets = ["n", "no", "nope", "nah", "non"]

name = input("What is your name?: ").strip().capitalize()
age = int(input("How old are you?: ").strip().lower())
place = input("Where do you live?: ").strip().capitalize()
work = input("What do you do for a living?: ").strip().lower()
hobbies = input("What is your favorite hobby?: ").strip().lower()
music = input("Who is your favorite musician?: ").strip().title()
travel = input("What country do you want to visit the most?: ").strip().capitalize()
pets = input("Do you have any pets? (y/n): ").strip().lower()

if pets in yes_pets:
    pets = "your furbaby"
elif pets in no_pets:
    pets = "that $$$"
else:
    while True:
        pets = input("Sorry didn't catch that. Do you have any pets (y/n)?: ").strip().lower()
        if pets in yes_pets:
            pets = "your furbaby"
            break
        elif pets in no_pets:
            pets = "that $$$"
            break

print("\nHi {}! You are {} years old and you live in {}.\nYou work as an {} but you do it for {}.\nWhen you're not working we could probably find you\n{} listening to some {}\ndreaming of going to {} someday.".format(name, age, place, work, pets, hobbies, music, travel))
Karthikeyan K
  • 229
  • 2
  • 7
0

you can use recursion for this

def test():
    yes_pets = ["y", "yes", "yeah", "yup", "yeah"]
    no_pets = ["n", "no", "nope", "nah", "non"]


    pets = input("Do you have any pets? (y/n): ").strip().lower()
    if pets in yes_pets:
        pets = "your furbaby"
        return pets

    elif pets in no_pets:
        pets = "that $$$"
        return pets
    else:
        return test()


name = input("What is your name?: ").strip().capitalize()
age = int(input("How old are you?: ").strip().lower())
place = input("Where do you live?: ").strip().capitalize()
work = input("What do you do for a living?: ").strip().lower()
hobbies = input("What is your favorite hobby?: ").strip().lower()
music = input("Who is your favorite musician?: ").strip().title()
travel = input("What country do you want to visit the most?: ").strip().capitalize()

pets = test()
nishant
  • 2,526
  • 1
  • 13
  • 19
  • While I don't think this is a good approach, I also don't think a human user could break the stack on any reasonably modern computer with this implementation. – Mad Physicist Jan 09 '19 at 07:04
0

Just add while loop:

yes_pets = ["y", "yes", "yeah", "yup", "yeah"]
no_pets = ["n", "no", "nope", "nah", "non"]

name = input("What is your name?: ").strip().capitalize()
age = int(input("How old are you?: ").strip().lower())
place = input("Where do you live?: ").strip().capitalize()
work = input("What do you do for a living?: ").strip().lower()
hobbies = input("What is your favorite hobby?: ").strip().lower()
music = input("Who is your favorite musician?: ").strip().title()
travel = input("What country do you want to visit the most?: ").strip().capitalize()
pets = input("Do you have any pets? (y/n): ").strip().lower()
while pets not in yes_pets+no_pets: // HERE
    pets = input("Sorry didn't catch that. Do you have any pets (y/n)?: ").strip().lower()
if pets in yes_pets:
    pets = "your furbaby"
elif pets in no_pets:
    pets = "that $$$"
print(
    "\nHi {}! You are {} years old and you live in {}.\nYou work as an {} but you do it for {}.\nWhen you're not working we could probably find you\n{} listening to some {}\ndreaming of going to {} someday.".format(
        name, age, place, work, pets, hobbies, music, travel))

Output:

C:\Users\Desktop>py xxx.py
What is your name?: aydin
How old are you?: 12
Where do you live?: aze
What do you do for a living?: program
What is your favorite hobby?: coding
Who is your favorite musician?: nobel
What country do you want to visit the most?: spain
Do you have any pets? (y/n): nikkilo
Sorry didn't catch that. Do you have any pets (y/n)?: aydin
Sorry didn't catch that. Do you have any pets (y/n)?: y

Hi Aydin! You are 12 years old and you live in Aze.
You work as an program but you do it for your furbaby.
When you're not working we could probably find you
coding listening to some Nobel
dreaming of going to Spain someday.
Rarblack
  • 4,559
  • 4
  • 22
  • 33
0

you can try with a while loop-

yes_pets = ["y", "yes", "yeah", "yup", "yeah"]
no_pets = ["n", "no", "nope", "nah", "non"]

name = input("What is your name?: ").strip().capitalize()
age = int(input("How old are you?: ").strip().lower())
place = input("Where do you live?: ").strip().capitalize()
work = input("What do you do for a living?: ").strip().lower()
hobbies = input("What is your favorite hobby?: ").strip().lower()
music = input("Who is your favorite musician?: ").strip().title()
travel = input("What country do you want to visit the most?: ").strip().capitalize()
pets = input("Do you have any pets? (y/n): ").strip().lower()
while pets not in yes_pets and pets not in no_pets:
    pets=input("Sorry didn't catch that. Do you have any pets (y/n)?: ").strip().lower()
if pets in yes_pets:
    pets = "your furbaby"
elif pets in no_pets:
    pets = "that $$$"
else:
    pass

print("\nHi {}! You are {} years old and you live in {}.\nYou work as an {} but you do it for {}.\nWhen you're not working we could probably find you\n{} listening to some {}\ndreaming of going to {} someday.".format(name, age, place, work, pets, hobbies, music, travel))

This will continue to loop and keep asking input until it does not get a valid value.

0

The expression yes_pets or no_pets evaluates to the first truthy operand. Since both lists are non-empty, your loop is effectively

for pets in yes_pets:

This will run five times no matter what since you don't break out of the loop. It will store nonsense input on the last iteration since there is no else clause.

You need a loop that will run indefinitely, and break out of it only when the user stops typing nonsense you can't understand. A while loop serves such a purpose admirably. It also eliminates some of the code duplication you have:

pets = input("Do you have any pets? (y/n): ").strip().lower()
while pets not in yes_pets and pets not in no_pets:
    pets = input("Sorry didn't catch that. Do you have any pets (y/n)?: ").strip().lower()

if pets in yes_pets:
    pets = "your furbaby"
else:  # pets in no_pets
    pets = "that $$$"

A different approach might be to use a dictionary of valid inputs that map to the correct output. That would speed up your search (lookup is now O(# of valid options), but would become O(1)). It would also make the loop a tad simpler, while allowing you to easily add options like "maybe":

pet_options = dict.fromkeys(yes_pets, 'your furbaby')
pet_options.update(dict.fromkeys(no_pets, 'that $$$'))

...

pets = pet_options.get(input("Do you have any pets? (y/n): ").strip().lower())
while pets is None:
    pets = pet_options.get(input("Sorry didn't catch that. Do you have any pets (y/n)?: ").strip().lower())
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
0

This code will work very well and very efficiently, it loops until the user types out anything starting with a "y" or an "n", it dosent matter if it is capitalized or not. You can remove the list of acceptable answers and impress your teacher.

from time import sleep
run = 0
while run == 0:
    response = input("Do you have any pets? (y/n): ")
    if response.upper()[0] == "Y":
        run += 1
        pets = "your furbaby"
    elif response.upper()[0] == "N":
        run += 1
        pets = "that $$$"
    else:
        print("That's not a yes or no answer!")
        sleep(1)