Command Palette

Search for a command to run...

Hectal
PHASE 1Beginner ~24 min· topic 6 of 11

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, str or bool. 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.

main.pywhole filepython
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.

main.pywhole filepython
print(int("42") + 1, float("3.5") * 2, str(99) + " balloons")
Text in, number outdiagram
Rendering diagram…

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.

main.pywhole filepython
print(int(3.9), int(-3.9), float(7), bool(0), bool("0"))
# 3 -3 7.0 False True

04What 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.

terminal
$ python main.py
── expected output ──
Traceback (most recent call last):
File "main.py", line 1, in <module>
count = int("3.5")
ValueError: invalid literal for int() with base 10: '3.5'

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).

main.pywhole filepython
age = 12
print("Age: " + str(age))      # Age: 12
print("5" * 3)                 # 555  (repeat the text)
print(int("5") * 3)            # 15

Try it yourself

  1. 1

    Spot the type

    Predict type(3 / 1), type(3 // 1), type("3" * 2) and type(3 > 2). Then print them.

  2. 2

    Repair a broken line

    Run print("Total: " + 40 + 2). Read the error. Then fix it two ways: with str() and with an f-string.

  3. 3

    Convert a price

    Take price_text = "199.99". Turn it into a float, double it, and print the result. Then try int(price_text) and read the error.

Code & diagrams

type, isinstance and the conversion functions New tab

Look at int("1_000"): underscores are allowed in text given to int().

Sign in to run this example in your browser.

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
Text versus number New tab

"5" + "5" joins text, int("5") + int("5") adds numbers. Same symbols, different types.

Sign in to run this example in your browser.

Expected output

55
10
Age: 5
3
555
3.0 True None
1000.0 1

Break 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.

main.pywhole filepython
count = int("3.5")
terminal
$ python main.py
── what you'll see ──
Traceback (most recent call last):
File "main.py", line 1, in <module>
count = int("3.5")
ValueError: invalid literal for int() with base 10: '3.5'

Break #2

Join text and a number with +

Add a number to a string.

main.pywhole filepython
age = 12
print("Age: " + age)
terminal
$ python main.py
── what you'll see ──
Traceback (most recent call last):
File "main.py", line 2, in <module>
print("Age: " + age)
~~~~~~~~^~~~~
TypeError: can only concatenate str (not "int") to str

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.

  • ▸

    isinstance is preferred over type(x) == int because it respects inheritance. It matters here too: type(True) == int is False, but isinstance(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") and float("1e3") are all accepted by float(), which is a quiet source of bugs when you validate user input. Check the result with math.isfinite. int() of those values fails: int(float("inf")) raises OverflowError and int(float("nan")) raises ValueError.

  • ▸

    int() and float() accept any Unicode decimal digits, so int("١٢٣") (Arabic-Indic digits) is 123, and underscores between digits ("1_000"). Silent widening can also lose information: int to float rounds beyond 2 ** 53 (float(2 ** 53 + 1) is 9007199254740992.0), and a huge int in a mixed expression raises OverflowError: int too large to convert to float instead of becoming inf. Python compares int and float exactly, though, so 2 ** 53 + 1 == float(2 ** 53 + 1) is False.

  • ▸

    bool conversions are about truthiness, not parsing, so bool("False") is True. For environment variables and config, write an explicit parser (value.strip().lower() in {"1", "true", "yes"}) or let Pydantic do it. str(x) calls x.__str__ and repr(x) calls x.__repr__; int(x) calls x.__int__ or x.__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. 1

    type(x) returns the type of a value: type(5) is <class 'int'>, type(5.0) is float, type("5") is str, type(True) is bool, and type(None) is NoneType. 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 as bool on int). 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. 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). Use round() if you want the nearest.

  3. 3

    Conversion can fail. int("3.5") is a ValueError, 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 and int("101", 2) is 5. It ignores spaces around the text and allows underscores between digits.

  4. 4

    Python converts between numbers silently when it must. 1 + 2.0 is 3.0: the int is widened to float before adding. The order is bool → int → float (then complex, a rare kind of number you can ignore for now). So True + 1.5 is 2.5. Python never converts between text and numbers without being told.

  5. 5

    That is why "Age: " + 5 is a TypeError. Python could guess, but guessing hides bugs: should "5" + 5 be 10 or "55"? It refuses. You choose: int("5") + 5 is 10, "5" + str(5) is "55".

  6. 6

    Python is dynamically typed: names have no fixed type, values do (x = 5 then x = "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

01

What is the difference between type(x) and isinstance(x, int)?

02

Why does Python refuse "5" + 5, and what are the two ways to resolve it?

03

What does int(-3.9) give, and what does that tell you about int() on floats?

04

What is the difference between a ValueError and a TypeError in conversions?

Practice

01

Convert the text "250" to a number, add 50, and print the total.

02

Turn the number 7 into text and use it to print Lucky number: 7 by joining strings with +.

03

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 isinstance with 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) and int("3.9") do, and why they differ.

  • Done when you can fix a TypeError caused by joining text and a number.