PYTHON / VARIABLES AND DATA TYPES
Type conversion and casting
Convert between Python's str, int, float, and bool deliberately, predict truncation and parsing failures, and know when Python promotes types for you.
What you will learn
- Use int(), float(), str(), bool() as constructors that return new objects
- Predict int(2.9) == 2 and int(-2.9) == -2: truncation toward zero, not rounding
- Parse integer text with int(s), decimal text with int(float(s)) or float(s)
- Catch ValueError from failed numeric parsing instead of assuming input is clean
Understanding Type conversion and casting
Python will not silently turn "42" into 42 or 42 into "42" for you. Conversion happens through calls like int(), float(), str(), and bool(), which are constructors: each one reads the object you pass and builds a brand new object of its own type. The original is untouched, so int(raw) does not change raw; you have to store the result somewhere. This is why casting in Python is closer to "construct a new value from this one" than to C-style reinterpretation of the same bits.
Inside the numeric types Python does convert implicitly, and the direction is always toward the type that can represent the result. Adding an int to a float promotes the int to float, so 3 + 1.5 is 4.5, and the / operator always produces a float even for 7 / 2. Because bool is a subclass of int, True and False already behave as 1 and 0 in arithmetic, which is why sum() over a list of comparison results counts them. Nothing crosses the boundary between numbers and strings automatically, which is exactly why "total: " + 3 raises TypeError.
Each conversion has a specific, learnable failure mode. int() applied to a float discards the fractional part toward zero, so it turns 2.9 into 2 and -2.9 into -2 and is never a rounding function. int() applied to a string demands a complete integer literal after whitespace is stripped, accepting a sign and digit-separating underscores but rejecting "19.99" with a ValueError, since a decimal point is not part of an integer literal. float() is more permissive with text but silently loses precision on very large integers, because a float has only 53 bits of significand.
raw = "42"
n = int(raw)
print(n + 8, type(n).__name__)
print(int(19.99), int(-19.99))
print(int("ff", 16), int("1_011"))
print(7 / 2, type(7 / 2).__name__)
print(str(3.0) + "!", float(" 2.5 "))
try:
int("19.99")
except ValueError as e:
print("ValueError:", e)Conversion functions build a new object of the target type from an existing value, and each one has a defined truncation or parsing rule you must know rather than guess.
Worked examples
int() truncates, round() rounds
Shows that int() cuts toward zero while round() moves to the nearest even value on ties.
for v in [2.7, -2.7, 2.5, 3.5]:
print(v, int(v), round(v))Example explained
Line 1int(2.7) is 2 and int(-2.7) is -2: the fractional part is dropped, so negatives move up toward zero.
Line 2round(-2.7) is -3 because rounding goes to the nearest value, not toward zero.
Line 3round(2.5) is 2 and round(3.5) is 4: exact .5 ties round to the even neighbour.
Line 4Using int() where you meant round() makes every non-integer result one step low.
What bool() considers false
Demonstrates that bool() conversion depends on emptiness or zero-ness, not on the text you see.
for value in [0, 0.0, "", "0", [], [0], None]:
print(repr(value), bool(value))Example explained
Line 1Numeric zero of any type converts to False, and every other number converts to True.
Line 2'0' is True because a string is false only when it has no characters at all.
Line 3[] is False but [0] is True: a one-element list is non-empty regardless of what it holds.
Line 4So bool(input()) is almost always True, since even "no" is a non-empty string.
Promotion inside numbers, refusal across the str boundary
Contrasts automatic numeric widening with the TypeError you get from mixing str and int.
count = 3
average = count + 1.5
print(average, type(average).__name__)
print(True + True)
try:
print("total: " + count)
except TypeError as e:
print("TypeError:", e)
print("total: " + str(count))Example explained
Line 1count + 1.5 promotes the int to float, so the result type is float, not int.
Line 2True + True is 2 because bool is a subclass of int and converts to 1 in arithmetic.
Line 3"total: " + count fails: + on a str requires a str, and Python refuses to guess.
Line 4str(count) performs the conversion explicitly and the concatenation then succeeds.
Important notes
int() with a base only accepts a string, not a number: int(1011, 2) is a TypeError, while int("1011", 2) is 11.
float() of a very large int loses precision: float(2**53 + 1) equals float(2**53), so round-tripping huge integers through float is not safe.
Common mistakes
Expecting int(2.7) to give 3: it gives 2, so totals computed from prices or averages come out systematically low.
Calling int("19.99") on user input, which raises ValueError: invalid literal for int() with base 10 and crashes the script instead of returning 19.
Writing int(answer) without reassigning it, so answer is still a string and the next arithmetic line fails with TypeError.
Try it yourself
Change, predict, then run
Given entries = ["3", "4.5", "abc", "10", ""], write a loop that tries float() on each item, adds successful conversions to a running total, and counts the failures. Print the total and the failure count.
Open the Python workspaceCheck your understanding
Why does int(7.0) return 7 while int("7.0") raises ValueError?
- int() parses a string as a complete integer literal, but truncates a float argument; they are two different conversion rules
- int() rejects any string that mixes digits with punctuation, regardless of what the punctuation means
- "7.0" is really a float, so it has to be passed through round() before int() will accept it
- int() only accepts string arguments when you also supply a base
Show answer
For a float, int() drops the fractional part, so 7.0 becomes 7. For a string, int() must parse text as an integer literal, and "." is not part of one, so it fails. Option 3 is tempting but wrong twice over: the fix is float("7.0") then int(), and round() is not required for a value that is already exact.