0

I want write a method that asks a user to input a digit, but if the user also inputs a string it needs to ask the user to input again until the correct data is input.

-------code that shows error-------------

def get_total():
    try:
        total = int(input("How many people you got in total: "))
    except:
        print("Your data is invalid, please try again.")
        get_total()
    return total

x = get_total()
print(x)

If you type 5 directly, it will print 5.
However if you type "s" first and then 5, it will throw this error:

"local variable 'total' referenced before assignment"

Can anyone could please tell me why?

If I correct the code like this, it works just fine

------code that works fine-----------------

def get_total():
    try:
        total = int(input("How many people you got in total: "))
        return total
    except:
        print("Your data is invalid, please try again.")
        return get_total()

x = get_total()
print(x)

So why does this happen?

Theo
  • 57,719
  • 8
  • 24
  • 41
  • You need the `while` loop, not recurrency. – Marcin Orlowski Jan 19 '19 at 14:41
  • 1
    You are returning something that hasn't been bound, there is no `total` if there was an exception. Don't use recursion to handle user input, see [Asking the user for input until they give a valid response](//stackoverflow.com/q/23294658) – Martijn Pieters Jan 19 '19 at 14:47
  • 1
    Next, `int()` will only ever throw `ValueError` in your scenario. Don't play Pokemon, you don't want to catch *all* exceptions. Only catch `ValueError`. – Martijn Pieters Jan 19 '19 at 14:48

4 Answers4

0

The reason is that if you enter 5 in first try it assigns total the value of 5 and then returns it

However if you enter the value "s" the except block gets run and it goes back to the function call . Then you enter the value 5 the return statment in the second function call returns 5 and it exits the except block in the first function call.

Then it runs the return statement however the variable total doesnt exist only the value 5 exists

correct code is

def get_total():
    try:
        total = int(input("How many people you got in total: "))
    except:
        print("Your data is invalid, please try again.")
        total = get_total() 
    return total

Hope it helps :)

Talha Israr
  • 654
  • 6
  • 17
0

I think this code is also correct:

def get_total():
    while True: # prompt's the user until a correct input is given(break)
        try:
            total = int(input("How many people you got in total: "))
            break # if the input for total is int, program will break from the loop. if not, program will print an error message and this loop will execute again
        except:
            print("Your data is invalid, please try again.")
    return total

x = get_total()
print(x)

hope it helps

Dariush Mazlumi
  • 186
  • 1
  • 3
  • 11
0

The problem is that when in the code

total = int(input("How many people you got in total: "))

the input is not a number and int throws an exception the local variable total has not been assigned. In the except part of the first version you are calling get_total recursively but this doesn't set the total variable, just returns you the result (that is ignored).

When (after this successful recursive call) you end up in your return statement the total variable is still unbound and therefore you get an exception.

The key point to understand is that calling get_total recursively is not a "goto". If you want a loop write a loop (e.g. using while), if you want recursion the use recursion.

6502
  • 112,025
  • 15
  • 165
  • 265
0

The error code should be modified as:

def get_total():
    try:
        total = int(input("How many people you got in total: "))
    except ValueError:
        print("Your data is invalid, please try again.")
        total = get_total()  # assign return value back to total
    return total

You don't receive the returned value from the function when you called within function, so when it encounters return total, Python throws UnboundLocalError.

A better way is to use an infinite loop like following:

def get_total():
    while True:
        try:
            total = int(input("How many people you got in total: "))
            return total
        except ValueError:
            print("Your data is invalid, please try again.")

Note that it's not advised to handle all exceptions once (like except:). Always name the exception with except keyword (ValueError in this case).

Austin
  • 25,759
  • 4
  • 25
  • 48