I'm fairly new to python (coding in general really), but I mostly grasp what's put in front of me. I'm trying to create an input that will only accept integers, so I put together the following function:
def askFor(request):
"""Program asks for input, continues to ask until an integer is given"""
num = ' '
while (isinstance(num, int) == False):
num = input(request)
else:
return num
it works fine when i enter a number, but anything else breaks it instead of looping it back. Am I missing an element, or am I just best off to go with
str(input('wargharble: '))
5 Answers 5
You are on the safer side with raw_input in Python 2, because it will always return a string, whereas input will try to evaluate the given string, which is dangerous.
def askFor(prompt):
""" ask for input, continues to ask until an integer is given
"""
number = None
while True:
try:
number = int(raw_input(prompt))
break
except ValueError:
pass # or display some hint ...
print(number) # or return or what you need ...
5 Comments
input evaluates the input as python code, while raw_input returns a string.The problem is that input() returns the raw user input evaluated as a python expression. So when you input something like "someinput" on the console here is what happens:
- The raw input is captured from the console as a string
- That string is then parsed as a python expression (so imagine you simply type this string into your program, in this case, it becomes a variable with the name "someinput"
- When isinstance() is called on this python expression, the python interpreter can't find a variable named "someinput" which is defined - so it throws an exception.
What you really want to do is use raw_input(), this will return a string representing the user's input. Since you are receiving a string from the console now though, you need some way of checking if a string is an int (because isinstance will always return a string)
Now to determine if the string is a number, you could use something like isdigit() - but be careful - this function will validate any string that contains only digits (so 0393 would be valid).
Here are the corrections that need to be made:
def askFor(request):
"""Program asks for input, continues to ask until an integer is given"""
num = ' '
while (num.isdigit() == False):
num = raw_input(request)
else:
return num
1 Comment
This is because input() is failing on non-integer input (this has to do with the fact that input() is calling eval() on the string your inputting (see python builtins).
raw_input() does not. (in fact, input() calls raw_input())
Try this instead:
while True:
num = raw_input(request)
if num.isdigit():
break
The isdigit() function checks to see if each character in a string is a digit ('0' - '9')
Comments
input evaluates whatever's typed in as Python code, so if the user types something non-sensical in, it'll produce an error. Or worse, it can run arbitrary commands on your computer. Usually, you want to use raw_input and convert the string value it returns safely yourself. Here, you just need to call int on the string, which can still produce an error if the user enters a non-int, but we can handle that by looping.
And voila:
def read_int(request):
while True:
try:
return int(raw_input(request))
except ValueError:
pass
Note, there's no need for break or else; just return the value once you have parsed it successfully!
Comments
Well first off, your indentation if a bit off (the while loop's indentation level does not match the previous level).
def askFor(request):
"""Program asks for input, continues to ask until an integer is given"""
num, isNum = '', False # multiple assignment
while not isNum:
num = input(request)
if type(num) in (int, long): # if it is any of these
isNum = True
break
else: isNum = False
return num # at the end of the loop, it will return the number, no need for an else
Another way to do it:
def askFor(request):
"""Program asks for input, continues to ask until an integer is given"""
num, isNum = '', False
while not isNum:
num = raw_input(request)
try: # try to convert it to an integer, unless there is an error
num = int(num)
isNum = True
break
except ValueError:
isNum = False
return num
3 Comments
type, which is a kind of last resort, if nothing else works (see also: stackoverflow.com/a/1549854/89391); in your second example you introduce too much clutter.input statement, two is used as a variable. As it is not defined, you will get a NameError. You could use try and except with that as well, or use raw_input; raw_input returns the user's input as a string, so then you can use a try to convert it to an integer, unless there is an error (most likely TypeError); then prompt them again.
while not isinstance(num, int):is a little more Pythonic thanwhile (isinstance(num, int) == False):. :)input()runseval()on whatever the user types in (see the docs), so if it's not valid Python syntax for a constant or literal expression, like42,1+2, or"Bob", an exception will be raised which your program will need to catch. I suggest you instead usenum = int(raw_input(request))within atry/exceptclause because it doesn't useeval()and is therefore safer.