Data Types
Identify Python's core types, int, float, str, bool, and understand what each represents.
- 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 apples and you cut one of them in half. Are you now holding apples in the same sense as you held ? Half an apple is not a whole number of apples, lives in , and lives in .
A mathematician answers by asking which set a value belongs to. The same distinction haunts every program: the machine stores differently from , and 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.
| Type | What it is, mathematically | Examples |
|---|---|---|
int | , the integers, stored exactly | 42, -7 |
float | , approximated with a fixed number of binary digits | 3.14, -0.5 |
str | a finite sequence of characters | "hello" |
bool | 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 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:
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:
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: , , the empty string
"", andNone - Truthy: everything else
bool(0) # False
bool(1) # True
bool(-1) # True — any nonzero number is truthy
bool("") # False
bool("hello") # True — any non-empty string is truthyNotice 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:
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 intRead 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 / 2is2.0, not2. True division (/) always returns afloatin Python 3, even when the division is exact. For an integer result, ask for floor division:4 // 2→2.True + Trueis2.boolis a subclass ofintin Python:Truebehaves as andFalseas in arithmetic. The two sets overlap, buttype(True)still answersbool.type()tells the concrete type.type(True)isbool, notint, no matter how comfortablyTrueplays along in sums.type()describes the result, not the operands.type(2 * 3.0)isfloat, aninttimes afloatlives in thefloatset. 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 with two decimal digits? Now explain why a float, which approximates with finitely many binary digits, cannot represent 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)isTrue, what single rule explains why is truthy but is falsy? Does the rule generalize from numbers to strings? - Python has
isinstance(42, int)which returnsTrue. Wouldisinstancebe more reliable thantype(x) == intfor checking types? Why? - Why does Python write
TrueandFalsecapitalized instead oftrueandfalse? 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?