1
votes

I'm new to Python. I came up with a simple program to test some of the tools I've learned. It works for the most part, except for one of my nested 'while' loops. Below is my code. The part that doesn't work is when I enter "manual" in my work function and it's "raining". I intended for it to print rainedOut then go back to the raw_input. Only once it's raining 3 times (i.e., after looping back to the raw_input 3 times and it being rainedOut) should it print "You should probably just give up now." and exit the function. However, what it does, is on the first go, it prints out rainedOut 3 times in a row and then ends the function automatically. Can anyone help me with the error in my code?

import time
import sys

done = "I'm tired of you. Goodbye."
rainedOut = "Sorry, rain foiled your plans :("
dontUnderstand = "I'm sorry, I don't understand."

def good_weather():
    """Imagine a world where every 5 seconds it rains (good_weather = False),
    then is sunny again (good_weather = True). This function should return
    whether good_weather is True or False at the time it's called.
    """
    seconds = time.time()
    seconds %= 10

    if seconds <= 5:
        good_weather = True
        return good_weather
    else:
        good_weather = False
        return good_weather

def start():
    entries = 0

    while entries < 4:
        choice = raw_input("Hello! What do you want to do right now? Options: 1) Sleep, 2) Work, 3) Enjoy the great outdoors: ")

        if choice == "1":
            print "We are such stuff as dreams are made on, and our little life is rounded with a sleep. - Shakespeare, The Tempest"
        elif choice == "2":
            work()
        elif choice == "3":
            outdoors()
        else:
            print dontUnderstand
            entries += 1
    print done

def work():
    entries = 0
    entries2 = 0

    while entries < 4:
        choice = raw_input("Would you prefer sedentary office work or manual labor in the elements?: ")

        if "office" in choice:
            print "The brain is a wonderful organ; it starts working the moment you get up in the morning and does not stop until you get into the office. -Robert Frost"
        elif "manual" in choice:
            sunny = good_weather()
            if sunny == True:
                print "A hand that's dirty with honest labor is fit to shake with any neighbor. -Proverb"
            else:
                while entries2 < 3:
                    print rainedOut
                entries2 += 1
                print "You should probably just give up now."
                sys.exit()
        else:
            print dontUnderstand
            entries += 1
    print done
    sys.exit()

def outdoors():
    sunny = good_weather()
    if sunny == True:
        print "Adopt the pose of nature; her secret is patience. -Ralph Waldo Emerson"
        sys.exit()
    else:
        print rainedOut
        start() # go back to start

start()
1
Never use sys.exit() to exit a loop, or function. Just return from the function. As to why you shouldn't, see numerous questions here. If that requires you to augment your function to return True/False status, or some more complicated object/None, then augment it. - smci
You should use break to exit from within a loop, return or return <exit-value/object> to return from a function, and you can shortcut breaking from a loop inside a function with a return (as long as you know what the return value will be). Do not use sys.exit() as some nuclear shotgun to escape all control-flow constructs! (Teardown, memory-leaks, housekeeping, message logging, GUI threads, persistent storage... just some of many reasons why it's a terrible habit. Also, it will screw up unit-tests/ Test-Driven Design) - smci
There is also no point in assigning a value to a variable and then immediately returning it. You're doing it at least twice (in good_weather). Use return True and return False instead. - Reut Sharabani
@ReutSharabani: in fact those six lines can all be replaced with return (seconds <= 5). - smci
Or the entire function with return (time.time() % 10) <= 5 - Reut Sharabani

1 Answers

2
votes

I think you want this part:

else:
    while entries2 < 3:
        print rainedOut
    entries2 += 1
    print "You should probably just give up now."
    sys.exit()

To be more like this:

if entries2 < 3:
    print rainedOut
    entries2 += 1
    continue # restart loop (optional)
else:
    print "You should probably just give up now."
    sys.exit()

You're confusing the while (loop) and if (test) functionality.