Casting
A cast only works when the value makes sense as the new type. For int() the text must be a whole number such as "-12", and for float() it may also contain one decimal point. If the value cannot sensibly represent the target type, the program stops with an error rather than guessing what you meant.
For example, int("4,000") stops with an error because the comma is just formatting, not part of a Python number. float("4,000") also fails. In each case the program stops at that line, so nothing after it runs.
Text containing a decimal point is a valid real number but not a valid integer, so int("18.99") fails. The value is numeric, just not a whole number, and int() will not quietly chop the .99 off text for you.
The fix is a chained cast: cast the text to a real first, then cast that real to an integer. Written as one expression, int(float("18.99")) works from the inside out, giving 18.99 and then 18. Now that the value is a real number rather than text, int() can do its normal job of dropping the fractional part.
A cast can be applied to the result of another cast, because each cast hands back an ordinary value of the new type. The rule is simply to work out the innermost cast first, then apply the next one to what it produced.
| Expression | Innermost cast gives | Result |
|---|---|---|
str(int(11.2)) | 11 | "11" |
float(int(12.8)) | 12 | 12.0 |
int(float("23.45")) | 23.45 | 23 |
Chaining is useful when data arrives in the wrong type twice over, such as text holding a decimal that you need as a whole number for counting.
# Text with a decimal point needs two casts to become an integer
distance = "7.65"
whole_km = int(float(distance))
print(whole_km)
print(whole_km + 3)
# A failed cast stops the program part-way through
label = "7 km"
print(int(label))Output:
7
10
ValueError: invalid literal for int() with base 10: '7 km' (line 9)