3 Replies - 778 Views - Last Post: 29 February 2012 - 01:15 PM Rate Topic: -----

#1 sterling.a  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 2
  • Joined: 29-February 12

New to python Program question

Posted 29 February 2012 - 02:31 AM

I'm a noob to programming and have a question about my code. It's a homework assignment which I'm trying to do a little extra on. Basically just trying to get into the habits of writing clean code (which I am well aware takes LOTS of practice) and making my programs as user-friendly and robust as possible. My question has to deal with what I believe to be called "input validation". For instance if you look at the newExpense variable in the ADD_EXPENSE function. Whenever something other than an integer is entered the program fails. Is there any basic method or statement that can be implemented to help avoid that? I've tried expense = int(raw_input("text")) with no success. Here is the code:


#budget program

def MAIN_MENU(userName):
    choice = "no"
    totalBudget = 4000.00
    

    while choice == "no":

        print
        print ("Welcome %s your budget is currently %.2f")  %(userName, totalBudget)
        print
        print ("Please make a selection from the menu below: ")
        print
        print ("    -1- Add New Expense ")
        print ("    -2- Remove Expense")
        print ("    -3- Add Revnue")
        print ("    -4- Remove Revenue")
        print ("    -5- QUIT")
        print
        userInput = input("Enter your selection: ")
        
        if userInput == 1:
            totalBudget = ADD_EXPENSE(totalBudget)
        elif userInput == 2:
            totalBudget = REMOVE_EXPENSE(totalBudget)
        elif userInput == 3:
            ADD_REVENUE()
        elif userInput == 4:
            REMOVE_REVENUE()
        elif userInput == 5:
            choice = "yes"
        else:
            print ("Invalid option please select a number between 1-5")
    
def ADD_REVENUE():
    pass

def REMOVE_REVENUE():
    pass
    

def REMOVE_EXPENSE(totalBudget):
    userInput = "yes"

    while userInput == "yes":
        expense = input("Enter the expense amount you would like to remove: ")
        frequency = input("Enter the frequency of the expense: ")
        totalExpense = expense * frequency
        print ("The total amount of expense to be remvove is $%.2f") %(expense)
        print ("Its frequency is %s") %(frequency)

        if totalExpense > 4000.00:
             print ("Unable to remove expense because it will cause your total budget to exceed $4000.00")
        elif totalExpense < 4000.00:
            totalBudget = totalBudget + totalExpense
            print("Expense removed")
            return totalBudget
    
    

def ADD_EXPENSE(totalBudget):

   userInput = "yes"

   while userInput == "yes":
       newExpense = int(raw_input("Enter expense amount: ")
                        
       frequencyEX = input ("How many times does expense need to be deducted this month? ")
       totalExpense = frequencyEX * newExpense

       if totalExpense > totalBudget:
           print ("Unable to accept new expense because it exceeds your total budget of: ")
           print ("$%.2f") %(totalBudget)
       elif totalExpense < totalBudget:
            totalBudget = totalBudget - totalExpense
            print ("Expense accepted you have a remaing balance of $%.2f") %(totalBudget)
            userInput = raw_input("Would you like to enter another expense? ").lower()
            if userInput == "no":
                return totalBudget
            
        
            
def GOODBYE_MESSAGE(totalBudget, userName):
    print ("Goodbye %s your ending budget is %.2f") %(userName, totalBudget)

def WELCOME_MESSAGE():
    print("Welcome to your personal budget program! ")
    print
    userName = raw_input("Please enter your name: ").title()
    return userName

def main():
    userName = WELCOME_MESSAGE()
    totalBudget = MAIN_MENU(userName)
    GOODBYE_MESSAGE(totalBudget, userName)
    
main()



any advice on cleaning this up is welcomed as well. thanks

Is This A Good Question/Topic? 1
  • +

Replies To: New to python Program question

#2 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2089
  • View blog
  • Posts: 3,182
  • Joined: 21-June 11

Re: New to python Program question

Posted 29 February 2012 - 03:33 AM

To handle malformed input you can either use int(raw_input()) and catch the exception that is thrown if the input is not valid or you can use raw_input() and then check whether the input is valid (with a regex for example) and if it is call int on it.

Regarding cleaning up your code: You shouldn't use strings as booleans. Please use True and False instead of "yes" and "no". It's also not proper Python style to name functions using ALL_UPPER_CASE. That looks rather jarring.

It also appears to me that you should either rename the choice variable to something like "quit" or get rid of choice and make the condition of the while loop while user_input != 5 (of course for that you'd need to initialize user_input before the loop like you do with choice). The way it is, the name of the variable doesn't really reflect what it does.

This post has been edited by sepp2k: 29 February 2012 - 03:36 AM

Was This Post Helpful? 2
  • +
  • -

#3 atraub  Icon User is offline

  • Pythoneer
  • member icon

Reputation: 759
  • View blog
  • Posts: 2,010
  • Joined: 23-December 08

Re: New to python Program question

Posted 29 February 2012 - 09:44 AM

If you're using python 2, don't use input, ever. It creates security vulnerabilities and creates a lot of potential errors. int(raw_input("your text")) will do what you're trying to do in a much safer way.

In terms of making sure that the input is an int, there are a couple approaches. For the sake of brevity, I'll go over a simple approach with you that should get the job done nicely.

def getInput(inputString, expectedType, errorString = False ):
    while True: #Continue indefinitely
        try: #try to do this, but an error could hit

            #use raw_input to communicate the inputString to the user and return the result after it's been casted to the type you're looking for
            return expectedType(raw_input(inputString)) 

        except ValueError as e:#This is error handling
            if errorString:#if you provided an errorString
                print errorString #print it
            else: #otherwise
                print str(e) #print the default python error
            print "Please try again\n"



Here's what the code does. you supply the text to communicate to the user, what type you are looking for, and optionally what to say if the user screws up (if you leave the last part blank it'll print out the basic error text, which is what I personally recommend). The function will try to cast the input to whatever type you specify. If an error is raised, we print the errorString (or the default python error) and ask the user to try again. At this point, we've reached the end of our loop, so the entire thing starts over. This loop will continue until the user enters a proper value.


I'm going to show you a quick test of the function in my shell.

>>> x = getInput("enter an int: ", int)
enter an int: Hi there, my name is adam, how are you today?
invalid literal for int() with base 10: 'Hi there, my name is adam, how are you today?'
Please try again

enter an int: five
invalid literal for int() with base 10: 'five'
Please try again

enter an int: 92
>>> print x
92



It's a simple and effective way to ensure you have an int. Later on, you really should learn about regular expressions (as sepp2k suggested) but to simply get you over this hump, this should work just fine.

This post has been edited by atraub: 29 February 2012 - 09:48 AM

Was This Post Helpful? 2
  • +
  • -

#4 sterling.a  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 2
  • Joined: 29-February 12

Re: New to python Program question

Posted 29 February 2012 - 01:15 PM

Outstanding! The getInput function works flawlessly. I must have looked over a dozen articles on using "try" and none of them made sense (to me at least). But , this works! Win!

I'm using 2.7 so thanks for the advice on not using "input".sepp2k as you recommended the use of actually booleans does make more sense, as well as your recommendation for the sentinel value and variable names. Remove the shocking ALL CAPS function looks a lot better as well. Thanks again, the information provided was extremely useful!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1