PyDA Course
📖 Lesson 3 Beginner ⏱ 15 min ⚡ +10 XP ColabKagglenbviewerBinderDeepnoteGitHub types · int · float · str · bool · dynamic-typing

Data Types

Identify Python's core types, int, float, str, bool, and understand what each represents.

🎯 What you'll learn:
  • Identify int, float, str, and bool values
  • Use type() to check a value's type
  • Understand dynamic typing in Python
  • Recognize truthy and falsy values

The set a number belongs to

Answer two questions: you have 77 apples and you cut one of them in half. Are you now holding 7+127 + \frac{1}{2} apples in the same sense as you held 77? Half an apple is not a whole number of apples, 77 lives in Z\mathbb{Z}, and 7127\frac{1}{2} lives in Q\mathbb{Q}.

A mathematician answers by asking which set a value belongs to. The same distinction haunts every program: the machine stores 4242 differently from 42.542.5, and 4242 differently from "42". The word Python uses for “which set this value lives in” is type.

So: how many sets are worth distinguishing? Four, at first.

TypeWhat it is, mathematicallyExamples
intZ\mathbb{Z}, the integers, stored exactly42, -7
floatR\mathbb{R}, approximated with a fixed number of binary digits3.14, -0.5
stra finite sequence of characters"hello"
bool{True,False}\{\text{True}, \text{False}\}True, False

The float row has a deliberate hedge in it, approximated. An integer is stored exactly, every time. A real number almost never is: how would you store 1/3=0.3331/3 = 0.333\ldots with a finite number of digits? You cannot, so Python keeps a finite approximation and the accounts differ in the trailing digits. That single fact explains a famous surprise you will meet shortly.

Asking which set

Given a value, you can ask its type directly:

python
type(42)      # <class 'int'>
type(3.14)    # <class 'float'>
type("hi")    # <class 'str'>
type(True)    # <class 'bool'>

Two notational notes. First, type(...) is a function, you hand it a value and it returns the type object that value belongs to. Second, the answer prints as <class 'int'>; the word class is Python’s term for a type, and the word in quotes is the set’s name. Read <class 'float'> as “belongs to the set float”.

A name does not commit to a set

Now the payoffs begin. In a language with static types you would declare up front: x is an integer. Python instead lets a name point wherever it likes:

python
x = 5
print(type(x))    # <class 'int'>
x = "hello"
print(type(x))    # <class 'str'>

Re-pointing a name to a different set is legal, so the type of x cannot be read from any declaration, only by asking what it currently points at. This is dynamic typing. It is convenient, and it is also the reason your program can silently hand a string to a function that expects numbers: nothing stops it until the operation itself fails.

Which values act like True?

Every value is either truthy or falsy, either it behaves as True in a condition or as False. The rule is compact, and it is worth verifying:

  • Falsy: 00, 0.00.0, the empty string "", and None
  • Truthy: everything else
python
bool(0)         # False
bool(1)         # True
bool(-1)        # True   — any nonzero number is truthy
bool("")        # False
bool("hello")   # True   — any non-empty string is truthy

Notice what is in the list and what is left out. -1 is True; 0 is not. The string "0" is True, it is non-empty, and emptiness is the criterion for strings, not the value of its content. This rule pays for itself the moment you write your first if: if score: means if score is not zero.

A worked example: auditing an expression

The sets pay for themselves the moment an expression mixes them. Read the receipt line by line and ask the set of each result:

python
unit_price = 4.75
quantity = 4
bill = unit_price * quantity     # float: the float absorbed the int
type(bill)                       # <class 'float'>
bool(bill)                       # True — any nonzero is truthy

type(10 / 2)                     # <class 'float'> — true division never returns int

Read bill as the product of two different sets. The sets do not “mix”, the float wins, because the proportion is not a whole number of any scale and the wider set must hold it. The audit habit is to ask the set directly: type(...) confirms what you suspected instead of betting on luck.

Common pitfalls

  • 4 / 2 is 2.0, not 2. True division (/) always returns a float in Python 3, even when the division is exact. For an integer result, ask for floor division: 4 // 22.
  • True + True is 2. bool is a subclass of int in Python: True behaves as 11 and False as 00 in arithmetic. The two sets overlap, but type(True) still answers bool.
  • type() tells the concrete type. type(True) is bool, not int, no matter how comfortably True plays along in sums.
  • type() describes the result, not the operands. type(2 * 3.0) is float, an int times a float lives in the float set. Do not predict from the pieces; ask the answer.

🧩 Challenges

🧩 Challenge, think first, then reveal

Predict type(7 / 2), then check.

💡 Answer: type(7 / 2) is float, true division (/) always produces a float in Python 3, even when both operands are ints and the quotient is a whole number.

🧩 Challenge, think first, then reveal

Predict bool(0), bool(0.0), bool(""), and bool("0"). Which are truthy, which falsy?

💡 Answer: bool(0) → False, bool(0.0) → False, bool("") → False (empty string), bool("0") → True (non-empty string, even though its content is the character "0").

🧩 Challenge, think first, then reveal

In Python, 0.1 + 0.2 does not equal 0.3. Here is the same problem on paper: what happens when you represent 1/3=0.3331/3 = 0.333\ldots with two decimal digits? Now explain why a float, which approximates R\mathbb{R} with finitely many binary digits, cannot represent 0.10.1 exactly.

💡 Answer: With two digits, $1/3$ must become $0.33$, a loss already made before any arithmetic. Likewise $0.1$ has no exact binary form; the float stores a nearby value, and adding two of these involves minuscule errors: 0.1 + 0.2 yields 0.30000000000000004, not 0.3. Finite precision, not a Python bug.

🤔 Socratic Questions

  • If bool(-1) is True, what single rule explains why 1-1 is truthy but 00 is falsy? Does the rule generalize from numbers to strings?
  • Python has isinstance(42, int) which returns True. Would isinstance be more reliable than type(x) == int for checking types? Why?
  • Why does Python write True and False capitalized instead of true and false? What other capitalized words does Python reserve?

✅ Quick check

1. What is the type of 3.14?

2. What is the result of True + True?

3. Which of these is falsy?

typesintfloatstrbooldynamic-typing