Topic 1.6
Checking and Converting Types
In one line
Every value has a type. type() and isinstance() tell you which, and int(), float(), str() and bool() convert between types when the conversion makes sense. Python never converts text and numbers silently, so "5" + 5 is an error.
Think of it like this
Money and a price tag. A price tag that says "5 rupees" is only writing on paper. You cannot buy tea with the tag; you need five rupees of real money. In Python 5 is the real quantity you can calculate with, and "5" is only the written character five. They look alike, but they are different types (kinds of value), and you must convert one into the other on purpose.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Type
- The kind of a value, such as
int,float,strorbool. It decides which operations work. - Conversion (casting)
- Making a new value of another type from an existing one, like
int("42"). - isinstance
- A function that answers whether a value is of a given type.
- Widening
- Python silently turning an int into a float when you mix them.
- Truncate
- Cut off the decimal part without rounding.
int(3.9)is 3. - ValueError
- The error for a right-type value with unusable content, like
int("abc"). - TypeError
- The error when an operation gets the wrong type, like
"a" + 1. - Dynamic typing
- Types belong to values, not to names, and are checked when the code runs.
Step by step
01Asking for the type
type shows exactly what Python thinks a value is. When code behaves strangely, printing type(x) is the fastest check. A very common cause: you think a value is a number, but it is text that looks like one.
print(type(5), type(5.0), type("5"), type(True), type(None))
print(isinstance(5, int), isinstance(5, float), isinstance(True, int))
print(isinstance(5, (int, float)))02Text in, number out
Anything a person types, and anything read from a file, arrives as text. Before you can calculate, you convert. int("42") + 1 is 43. Without the conversion, "42" + 1 is an error.
print(int("42") + 1, float("3.5") * 2, str(99) + " balloons")03Cutting versus rounding
int(3.9) is 3, and int(-3.9) is -3. The fraction is thrown away, so the number moves toward zero. If you want 4, use round(3.9). Pick the one that matches your meaning: a price rounded to the nearest rupee is not the same as the price with the paise cut off.
print(int(3.9), int(-3.9), float(7), bool(0), bool("0"))
# 3 -3 7.0 False True04What fails
int("3.5") fails because int accepts only whole-number text. The two-step int(float("3.5")) works and gives 3. int("abc") fails with the same ValueError. The error message always shows the text it could not convert, which helps you debug.
05Numbers widen silently, text never does
Mixing int and float works, and the answer is a float: 1 + 2.0 is 3.0. Mixing text and a number does not. "Age: " + age fails with TypeError: can only concatenate str (not "int") to str. The cure is str(age), or an f-string (Topic 1.9).
age = 12
print("Age: " + str(age)) # Age: 12
print("5" * 3) # 555 (repeat the text)
print(int("5") * 3) # 15Try it yourself
- 1
Spot the type
Predict
type(3 / 1),type(3 // 1),type("3" * 2)andtype(3 > 2). Then print them. - 2
Repair a broken line
Run
print("Total: " + 40 + 2). Read the error. Then fix it two ways: withstr()and with an f-string. - 3
Convert a price
Take
price_text = "199.99". Turn it into a float, double it, and print the result. Then tryint(price_text)and read the error.
Code & diagrams
Look at int("1_000"): underscores are allowed in text given to int().
Expected output
<class 'int'> <class 'float'> <class 'str'> <class 'bool'> <class 'NoneType'>
True False True
True
43 7.0 99 balloons
3 -3 7.0 False True
12 1000 255 5
3.0 <class 'float'> 2.5"5" + "5" joins text, int("5") + int("5") adds numbers. Same symbols, different types.
Expected output
55
10
Age: 5
3
555
3.0 True None
1000.0 1Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
int() on decimal text
Convert "3.5" straight to an int.
count = int("3.5")Break #2
Join text and a number with +
Add a number to a string.
age = 12
print("Age: " + age)Myth vs fact
Myth
int("3.5") returns 3.
Fact
It raises a ValueError. Only int(3.5) (a float) returns 3. For decimal text, go through float first.
Myth
int() rounds to the nearest whole number.
Fact
int() cuts the fraction off toward zero. int(-3.9) is -3. Use round() for the nearest.
Myth
Python is weakly typed because you don't declare types.
Fact
Python is dynamically typed (types belong to values) and strongly typed (it refuses to mix incompatible types). "a" + 1 is an error, unlike in some languages that guess.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
isinstanceis preferred overtype(x) == intbecause it respects inheritance. It matters here too:type(True) == intis False, butisinstance(True, int)is True. If you must exclude bools, check them first. - ▸
Everything a user types or a file holds starts as text: JSON numbers, CSV cells, environment variables, command-line arguments. Real programs convert and validate at the edge, and then work with proper types inside. Pydantic (Phase 15) does this conversion and checking automatically from type hints.
- ▸
float("nan"),float("inf")andfloat("1e3")are all accepted byfloat(), which is a quiet source of bugs when you validate user input. Check the result withmath.isfinite.int()of those values fails:int(float("inf"))raisesOverflowErrorandint(float("nan"))raisesValueError. - ▸
int()andfloat()accept any Unicode decimal digits, soint("١٢٣")(Arabic-Indic digits) is 123, and underscores between digits ("1_000"). Silent widening can also lose information:inttofloatrounds beyond 2 ** 53 (float(2 ** 53 + 1)is9007199254740992.0), and a huge int in a mixed expression raisesOverflowError: int too large to convert to floatinstead of becominginf. Python compares int and float exactly, though, so2 ** 53 + 1 == float(2 ** 53 + 1)isFalse. - ▸
boolconversions are about truthiness, not parsing, sobool("False")isTrue. For environment variables and config, write an explicit parser (value.strip().lower() in {"1", "true", "yes"}) or let Pydantic do it.str(x)callsx.__str__andrepr(x)callsx.__repr__;int(x)callsx.__int__orx.__index__, which is how your own classes become convertible (Topic 8.7). - ▸
NumPy and pandas add their own types (
int32,float64,datetime64), and silent conversions happen there more often. Machine learning code is full of casts like.astype(float); knowing the Python rules first makes them easier to follow.
Remember this
- 1
type(x)returns the type of a value:type(5)is<class 'int'>,type(5.0)isfloat,type("5")isstr,type(True)isbool, andtype(None)isNoneType.isinstance(x, int)answers yes or no and is the better choice inside code, because it also accepts subclasses (types built on another type, such asboolonint). You can ask about several types at once by listing them in round brackets, which makes a tuple (Phase 4):isinstance(5, (int, float)). - 2
The conversion functions are named after their types.
int("42")reads whole-number text and gives 42.float("3.5")reads decimal text.str(99)gives the text"99".bool(x)follows the truthiness rules (Topic 1.4).int(3.9)gives 3: converting a float to an int cuts off the fraction toward zero (int(-3.9)is -3). Useround()if you want the nearest. - 3
Conversion can fail.
int("3.5")is aValueError, because "3.5" is not whole-number text. To go from the text "3.5" to 3, convert in two steps:int(float("3.5")).int()also accepts a base:int("ff", 16)is 255 andint("101", 2)is 5. It ignores spaces around the text and allows underscores between digits. - 4
Python converts between numbers silently when it must.
1 + 2.0is3.0: the int is widened to float before adding. The order isbool→int→float(thencomplex, a rare kind of number you can ignore for now). SoTrue + 1.5is2.5. Python never converts between text and numbers without being told. - 5
That is why
"Age: " + 5is aTypeError. Python could guess, but guessing hides bugs: should"5" + 5be 10 or "55"? It refuses. You choose:int("5") + 5is 10,"5" + str(5)is"55". - 6
Python is dynamically typed: names have no fixed type, values do (
x = 5thenx = "five"is allowed). It is also strongly typed: it refuses operations that mix incompatible types. Type hints (Phase 10) let you document the types and let tools check them without changing how Python runs.
Explain it without notes
What is the difference between type(x) and isinstance(x, int)?
Why does Python refuse "5" + 5, and what are the two ways to resolve it?
What does int(-3.9) give, and what does that tell you about int() on floats?
What is the difference between a ValueError and a TypeError in conversions?
Practice
Convert the text "250" to a number, add 50, and print the total.
Turn the number 7 into text and use it to print Lucky number: 7 by joining strings with +.
Turn the text "9.99" into a whole number by cutting off the decimals, and print it.
Trade-offs
- ↔
Strict vs. forgiving. Python's strict rules produce errors early, instead of weird results later. The cost is a few explicit conversions.
- ↔
Convert early vs. convert late. Converting input to the right type as soon as it enters the program keeps the rest of the code simple, but you must handle bad input right there.
Done when you can
Done when you can name the type of any simple value using
type().Done when you can use
isinstancewith one type and with a tuple of types.Done when you can convert text to int and float, and number to text.
Done when you can say what
int(3.9)andint("3.9")do, and why they differ.Done when you can fix a
TypeErrorcaused by joining text and a number.