Rotes328
Rotes328

Reputation: 23

Returning a Value from a Recursive Python Function

Edit: I should have said up front that I know this isn't the best way to do it; I was specifically trying to use recursion for this to learn about it.

I'm new to Python with beginner knowledge of programming and I'm running into an issue with recursion and error-handling. I have this function that takes user input to get a variable for my program:

1    def get_seconds():
2        a = input("Run how often in seconds (1-60, q to Quit)? ")
3        if a.lower() == "q":
4            exit()
5        try:
6            int_a = int(a)
7            if int_a < 1 or int_a > 60:
8                print("Interval must be between 1 and 60.")
9                get_seconds()
10               return(int_a)
11           else:
12               return(int_a)
13       except:
14           print("Interval must be an integer between 1 and 60.")
15           get_seconds()
16    
17   c = get_seconds()
18   print(c)

The idea is that if the user inputs Q or q, it quits immediately. If the user inputs a number between 1 and 60 inclusive, that value is returned. I'm running into the following issues though:

If I input all integers, only the first value is returned:

Run how often in seconds (1-60, q to Quit)? 99
Interval must be between 1 and 60.
Run how often in seconds (1-60, q to Quit)? -20
Interval must be between 1 and 60.
Run how often in seconds (1-60, q to Quit)? 5
99

If I use other data types causing int_a = int(a) to fail, I get a return of None:

Run how often in seconds (1-60, q to Quit)? 5555.9999
Interval must be an integer between 1 and 60.
Run how often in seconds (1-60, q to Quit)? -5
Interval must be between 1 and 60.
Run how often in seconds (1-60, q to Quit)? 5
None

I'm having trouble tracking the contents of the variables through this. Basically the first variable that passes the 'int_a = int(a)' becomes what is returned, regardless of the recursion.

Any help is much appreciated!

Upvotes: 0

Views: 259

Answers (4)

lhiradi
lhiradi

Reputation: 1

def get_seconds():

        a = input("Run how often in seconds (1-60, q to Quit)? ")
        if a.lower() == "q":
         exit()

        try:
            int_a = int(a)
            if 1 <= int_a <= 60:
                print(int_a)
                exit()

            else:
                print('Interval must be between 1 and 60.')
                get_seconds()

        except ValueError:
            print("Interval must be an integer between 1 and 60.")
            get_seconds()


c = get_seconds()
print(get_seconds())

Hi. it will solve your problem, I just edit somethings in code. just fix indents by yourself. good luck!

Upvotes: 0

Patrick Artner
Patrick Artner

Reputation: 51683

See Wasif's answer for why yours does not work - your code does not return values on all code paths.

Using recursion for this task is bad, use a simple loop and break/return from it:

def get_seconds():
    while True:
        a = input("Run how often in seconds (1-60, q to Quit)? ")
        if a.lower() == "q":
            exit()
        try:
            int_a = int(a)
            if 1 <= int_a <= 60:   # return if valid, this leaves the while loop 
                return int_a
        except ValueError:         # catch specific errors
            print("Interval must be an integer between 1 and 60.")

c = get_seconds()

You can find more on this in Asking the user for input until they give a valid response

Upvotes: 3

Prune
Prune

Reputation: 77900

You have problems on several levels. The process problem is that you've written a four-lobed subroutine without testing the individual code blocks. The structural problem is that you're using recursion to do a job better suited for simple iteration. See iterate until valid input.

The functional problem is that the only time you return a value is from the top level of calls:

print("Interval must be between 1 and 60.")
get_seconds()
return(int_a)

Your code here is clearly dysfunctional

  • issue an error message
  • recur to get new input ... and ignore any returned value
  • return the local value that made you print the error message.

In a recursion situation, you would take the value you get from the recursive call and pass it back up the call stack.

print('error')
return(get_seconds())

Upvotes: 1

wasif
wasif

Reputation: 15508

You need to explicitly return the inner recursive call value too. In the last line of function use return get_seconds() instead of get_seconds()

Upvotes: 4

Related Questions