Mark S.
Mark S.

Reputation: 29

Running exceptions within a function - Python

I've been learning Python for about 3 weeks now, so what I'm working on is obviously going to be very simple. I've already written a couple programs that return values for certain calculations, and I have successfully used exceptions within functions in those programs. The program that I'm currently working on is only for the purpose of me getting some more practice writing functions, while loops, and exceptions. Here's what I've got so far:

def factorial(n):
    while n > 0:
        return n * factorial(n-1)
    return 1

    print factorial(n)

def user():
    n = int(raw_input("What number would you like to use?"))
    try:
        factorial(int(n))
    except ValueError:
        print "You must choose a number. Please try again."
        return user()


if __name__ == '__main__':
    user()

I can't figure out why my exception within the user() function doesn't seem to be running. All I get when I run this code is the raw_input "What number would you like to use?". The factorial() function doesn't run, nor do the print or return statements that I've set if there is a ValueError. Can anyone help me figure out why this is (or rather isn't) happening?

Upvotes: 1

Views: 1427

Answers (3)

dawg
dawg

Reputation: 103754

Here are my comments expanded into an answer.

First, do not print inside the factorial function. Print the value returned from that function:

def factorial(n):
    while n > 0:
        return n * factorial(n-1)
    return 1

>>> factorial(4)
24

Next, wrap the thing that you think will cause the exception in the try part of the block. In this case, the call to int with unknown user input might cause an exception; wrap that in the try -- no more. Finally, do not use recursion for user input. Use a while loop instead:

def user():
    n=None
    while not n:
        user_int=raw_input("What number would you like to use? ")
        try:
            n=int(user_int)
        except ValueError:
            print "You must choose a number. Please try again."

    print factorial(n)   

if __name__ == '__main__':
    user() 

Upvotes: 1

Nerketur Kamachi
Nerketur Kamachi

Reputation: 19

Funny enough, all of the code is running! It just isn't showing anything, because the print statement isn't being called! Lets decompose the user function and see what it does.

What the code is doing

n = int(raw_input("What number would you like to use?"))

Convert the string the user types into an integer and store it into the variable (or, if you want to be pythonic-ly correct, the name) n.

try:
    factorial(int(n))

Try to convert n into an integer (again) and send said integer to the factorial function. Note that n here is already an integer! So this will always succeed. Just call the function, nothing more.

except ValueError:
    print "You must choose a number. Please try again."
    return user()

If ValueError is raised, print an error message, then return the value of user.

We don't print anything whether the conversion was successful or not. We just run a single function then exit. What function do we run?

def factorial(n):
    while n > 0:
        return n * factorial(n-1)
    return 1

    print factorial(n)

Note that in this function the code says to print a value after returning a value. Once a function returns, nothing after the return statement is run. The print statement will not be executed! So this function correctly computes the factorial (recursively), and returns it. Nothing else!

This is why your program will seem to do nothing. This function is called, computes, and returns the answer. The returned answer is simply ignored!

What does this mean?

There are three key lines in your code that define why it's doing what it's doing.

  1. You convert the input from the user into an integer and store it in n
    • This will raise ValueError if the user types anything that isn't an integer.
    • Note that this still happens! if you run the code, type b, then press enter, an exception (ValueError) will be raised.
  2. You convert n into an integer and pass it to factorial.
    • Although this is in the try block (as it should be), n is already an integer. This is why your exception code will never run.
  3. Your only print statement (after getting valid input from the user) is inside the factorial function, after the return statement. It will never be executed. This is why nothing is printed.
    • I don't recommend printing the result inside of a recursive function. It can be done, but it is generally better to return the result and print the returned value, outside of the recursive function. (perhaps in the user function, instead of calling factorial(n) printing what it returns would be better!)

I hope that this helped to clarify exactly what is going on with the code, and I hope I was able to answer your question! Happy coding! :D

Upvotes: 1

Anupam
Anupam

Reputation: 717

first of all you have to print the factorial(int(n)) to see the output, And remove int conversion of your input,

here is my modified code:

def factorial(n):
  2     while n > 0:
  3        return n *factorial(n-1)
  4     return 1
  5     print factorial(n)
  6 
  7 
  8 
  9 
 10 def user():
 11     n = raw_input("What number would you like to use?")
 12 
 13     try:
 14 
 15         print factorial(int(n))
 16     except ValueError:
 17         print "You must choose a number. Please try again."
 18         return user()
 19 
 20 if __name__ == '__main__':
 21     user()

hope this helps,

Upvotes: 0

Related Questions