[Tutor] exceptions problem

Steven D'Aprano steve at pearwood.info
Mon Sep 13 13:59:03 CEST 2010


On Mon, 13 Sep 2010 08:55:46 pm Francesco Loffredo wrote:
> I don't like this rough behaviour of int(), spitting out an
> exception if given a legitimate string representation of a float. Can
> some of you Tutors explain me why it must be so?

The int() function behaves as a constructor, producing an integer object 
from its argument. It has two jobs:

(1) truncate (round-to-zero) numbers to a whole number by dropping any 
fraction part without rounding; and

(2) convert strings to an integer.


So int() can truncate all of these numbers:

>>> from decimal import Decimal
>>> from fractions import Fraction
>>> int(3)  # an int is already an int, so no change
3
>>> int(5.6)
5
>>> int(Decimal("-1.2"))
-1
>>> int(Fraction(12, 5))
2


But not this one, because it's not clear what the integer part of a 
complex number is:

>>> int(5.23 + 11.76j)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't convert complex to int


Okay, that's numbers out of the way. Pretty straightforward.

When it comes to strings, we're doing *conversions*, not truncation, so 
we need to decide what are the rules for converting strings. The usual 
rule is that, apart from a possible leading + or - sign, we expect a 
string of digits. Nobody expects int("two hundred and thirty-seven") to 
return 237. What digits are allowed? That depends on the base -- Python 
supports bases from 2 to 36:

>>> int("123")  # base 10 is the default
123
>>> int("123ff", 16)  # hexadecimal
74751
>>> int("123ff", 36)
1777371

There's also a "base 0", which uses the string's prefix to specify the 
base:

>>> int("0x123ff", 0)  # 0x... means a hex number
74751


So what are we to make of a string like "1.95"? Obviously it's not an 
integer, and "." is not a valid digit. If you, the programmer, are 
reading in data from a file and are expecting *integers*, and somebody 
slipped in a decimal-point, that is just as troublesome as if they 
slipped in a semi-colon or the letter Z. Should "1.95" be truncated to 
1, or rounded to 2? Should it remain a float? Should the dot be 
interpreted as a digit in some unusual base?

Python refuses to guess what int("1.95") should mean, and it raises an 
error, just as it does for int("1+1") or int("two").


-- 
Steven D'Aprano


More information about the Tutor mailing list