int — arbitrary precision, no overflow
Python's int has no maximum. Other languages give you 32-bit or 64-bit integers and overflow when you exceed them. Python expands its integer representation as needed — multiply two ten-digit numbers and you get a twenty-digit answer, no special syntax, no library. CPython implements this behind the scenes; you just get correctness.
This is more useful than it sounds. Cryptography, combinatorics, large-scale counting — domains that fight overflow in C/Java work straightforwardly in Python. The cost is a small per-operation overhead; for normal numbers it's invisible.
Integer literals support multiple bases — 0x for hex, 0o for octal, 0b for binary. Underscores are allowed inside literals for readability — 1_000_000 reads better than 1000000. Bitwise operators (& | ^ ~ << >>) work on ints directly.
float — IEEE 754, and the 0.1 + 0.2 trap
Python's float is a 64-bit IEEE 754 double-precision number — same representation every modern language uses. That representation cannot exactly express most decimal fractions. 0.1 in binary is a repeating fraction (like 1/3 in decimal); the stored value is approximately, not exactly, 0.1.
This means 0.1 + 0.2 == 0.3 is False. The actual sum is 0.30000000000000004. This is not a Python bug — it's how floating-point math works everywhere. Every language gets this wrong the same way.
==. Use math.isclose(a, b), which compares within a tolerance. The default tolerance is reasonable for most cases; tighten it if you need to.
Decimal — when float won't do
For domains where exact decimal representation matters — money, scientific measurements, anything regulated — use decimal.Decimal instead of float. Decimal stores the digits exactly and lets you control rounding behavior precisely.
Performance is slower than float (maybe 100×), so don't reach for Decimal for hot loops. But for an invoice total, a tax calculation, a financial report — Decimal is the right type.
bool — True, False, and the rest
Python's bool has two values — True and False. Capitalized; true is a NameError. Bool is actually a subclass of int — True == 1 and False == 0, and you can do arithmetic with them (sum([True, True, False]) gives 2). This is occasionally useful, occasionally surprising.
None — the absence object
None is Python's null. It's a singleton — there is exactly one None object, and every reference to None points at the same one. That's why if x is None works — identity comparison against the singleton.
Functions that don't explicitly return something return None implicitly. Default arguments are often None. Database NULL values come back as None. You'll see it everywhere; treat it as "no value here."
Truthiness — what counts as "true" in Python
Python's if doesn't only accept booleans. Any value can be evaluated for truthiness. The rules:
- Falsy —
False,None,0,0.0,""(empty string),[](empty list),{}(empty dict),()(empty tuple),set()(empty set) - Truthy — everything else, including non-empty strings, non-zero numbers, non-empty collections
This enables the Pythonic idiom if items: instead of if len(items) > 0:. Both work; the first is the idiom. The Pythonic track digs into the trade-offs.
if response_text: instead of if response_text != "":, if user.session: instead of if user.session is not None:. The shorter form lets the reader focus on the question ("do we have a thing?") instead of the mechanism ("compare to empty/null").
Type conversion — int(), float(), str(), bool()
Each built-in type doubles as a constructor that converts other values. int("42") parses a string. float("3.14") too. str(42) goes the other way. bool(0) gives False; bool([]) gives False; bool("hello") gives True.
Two gotchas worth remembering — int("3.14") raises ValueError because string "3.14" isn't an integer. To go from string to int via float — int(float("3.14")) gives 3. And bool("False") gives True because the string "False" is non-empty (truthy). Use explicit comparison or a JSON-aware parser if you're reading boolean-ish strings.
Bottom line
int has no max. float can't exactly represent 0.1. Decimal exists for when float isn't enough. None is a singleton. Truthiness covers more than booleans. These five facts cover 95% of type-related surprises in Python.
if items:, not if len(items) == 0:). Use is None for None checks (not == None). Use math.isclose for float comparison (not ==). Use Decimal for money. Each of these is a one-line change that future-you will thank present-you for.