FarTooFickle FarTooFickle - 22 days ago 5
Python Question

Sometimes get a ValueError from passing a float to int() method, but not always

Python newbie here. I've been messing around with flow control and have come across a situation I don't quite understand related to exceptions.

In the following code I want the user to enter an integer in a given range and, in the case of non-compliance, keep asking them until they give a valid value:

while True:
try:
x = int(raw_input("Pick an integer between 2 and 9. "))
except ValueError:
print "Please enter an integer!"
continue
else:
if 2 <= x <= 9:
print("Your number is {0}.").format(x)
break
else:
print "That's not between 2 and 9!"
continue


As far as I can tell, this code works exactly as I want it to. I've thrown every other type of input I can think of at it and it only lets you exit the loop when an integer from 2-9 is entered. Not even floats are accepted.

My question is, given that
int()
can be successfully called on floats,

>>> int(2.1)
2


why does this try/except construct raise the exception when the input is a
float
? If I run the code without the try/except statements and enter anything other than an integer, it throws an error and exits.

I'm running python 2.7 from windows powershell.

Answer

This is because raw_input returns a string.

Under the hood, when you call int, it actually calls an objects object.__int__() method. This is different from object to object.
For a float, this truncates a value (Rounds towards 0).
On a string, it tries to parse an int according to https://docs.python.org/3/reference/lexical_analysis.html#integer-literals (Which can't have a .).