0
\$\begingroup\$

I am very very new to programming, and this is my first day using Python.

I want to check to see if an input is of type 'int' and to proceed with my program if the user has entered an 'int', otherwise to print some error message, followed by a prompt to the user to try again.

What I have:

user_in = input('Input an integer value')
if type(user_in) == int:
    a = user_in
else:

I'm really not sure what to do here, or if its even possible to achieve this way, hence the blank line after 'else:'! I tried it with a while loop with try and excepts such as this:

while True: 
    try: 
        user_in = int(input('Enter an integer value'))
        a = user_in
    except:
        print('Invalid input, please try again')

Which works good for the exception case (because of the while True essentially acting infinitely), but of course, does not move on to the next part of the code in the case where an integer has successfully been inputted.

\$\endgroup\$
1
  • 5
    \$\begingroup\$ What version of Python are you using? @Linny seems to have taken the liberty of adding a python-3.x tag, but your first code snippet wouldn't work in Python 3. Please clarify the question. (And if you are indeed learning Python 2 as a beginner, please don't! It's due to become obsolete at the end of the year.) \$\endgroup\$ Sep 14, 2019 at 3:20

2 Answers 2

5
\$\begingroup\$

Your first code snippet has the problem that (in Python 3) input always returns a string, so type(user_in) will always be str, which will never compare equal to int.

Your second code snippet solves the problem in the correct way: try to convert the result to an integer, and catch the exception in case that fails.

Fixing that code is as simple as adding a break statement:

while True: 
    try: 
        user_in = int(input('Enter an integer value'))
        break
    except ValueError:
        print('Invalid input, please try again')
# do something with user_in here

There's no reason to assign the result to user_in and then to a. If you want it to be in a variable called a, just assign it to a to begin with.

Also, you should catch the specific exception that you are looking for, in this case ValueError. Catching every exception is almost never a good idea, because this code could fail for reasons other than the user entering something invalid. For example, if you inadvertently used input as a variable elsewhere in the same function, this call of it will probably raise a TypeError or NameError, and you'll want to see that error, not an infinite loop of "Invalid input, please try again".

\$\endgroup\$
2
  • \$\begingroup\$ It's unclear whether input() always returns a string. It doesn't, in Python 2. It was @Linny who added the python-3.x tag to the question, and I can't tell what that decision was based on. \$\endgroup\$ Sep 14, 2019 at 3:23
  • \$\begingroup\$ I didn't add that tag, but it was a good addition as it was what I was using. And thank you @benrg, very clear help! Much appreciated \$\endgroup\$
    – mystic96
    Sep 15, 2019 at 0:15
0
\$\begingroup\$

There are a lot of ways to accomplish this, one of them is to use recursion. Where in you write a "function" which executes your code & when you hit a certain condition, the function calls itself -

def myf():
    user_in = input('Input an integer value \n')
    if type(user_in) == int:
        a = user_in
        # continue with whatever you need to do with your code
    else: # if user_in is not an int, call your function again, this step keeps repeating unless use enters a valid integer
        print "You have not entered a valid integer, please try again"
        myf()

# call your function
myf()

Here, you are writing a function named myf(). You ask for an integer value to be entered by a user. You then check if the value entered is indeed an integer, if it is then you enter the "if" condition can continue rest of your code doing whatever you need to. If it is not an integer, you enter the "else" condition where the function calls itself.

At this point, the cycle repeats itself.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ input always returns a string, so type(user_in) == int will never be true. Also, each recursive call will add a frame to the stack, and the stack is often limited to 1000 frames, so holding Enter on autorepeat could crash the program. \$\endgroup\$
    – benrg
    Sep 14, 2019 at 2:44
  • \$\begingroup\$ Yeah, I just tried this out. It always ends up going to the else case because it's never an int. \$\endgroup\$
    – mystic96
    Sep 14, 2019 at 2:49
  • \$\begingroup\$ BUT... Thanks maverick928, I used what you suggested (recursion) with the try and except case and that seems to have worked! Not sure how to add code to this comment but if anyone else comes across this an needs help: define a function, use a try and except case, and in the except case, recursively call the same function. \$\endgroup\$
    – mystic96
    Sep 14, 2019 at 2:51
  • 2
    \$\begingroup\$ Don’t use recursion to implement a simple loop. In languages that support tail call optimization, it may be acceptable, but Python does not do tail call optimization, so it is a terrible abuse, and can lead to stack overflow. \$\endgroup\$
    – AJNeufeld
    Sep 15, 2019 at 0:37
  • \$\begingroup\$ While loops don't create a scope, functions definitely do. After calling myf and (successfully) entering user input, neither user_in nor a are accessible from the outside. You have to return the result. And, of course, just use a loop like others suggested. \$\endgroup\$
    – Graipher
    Sep 15, 2019 at 11:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.