Python Foundations — Variables, Types, Memory & Control Flow
Python's Memory Model — How Objects Really Work
Before writing a single line of useful code, you need to understand what Python is actually doing when you type x = 42. This mental model will save you hours of debugging confusion later.
In Python, everything is an object. An integer is an object. A string is an object. A function is an object. Even None is an object. Each object lives somewhere in memory and has three attributes baked into it:
- Identity — its unique address in memory (returned by
id()) - Type — what kind of object it is (returned by
type()) - Value — the data it holds
When you write x = 42, Python does NOT create a variable that contains 42. Instead:
- Python creates an
intobject in memory with value42 - Python binds the name
xto that object
The name is just a label pointing at an object. This distinction is fundamental.
Identity vs Equality: is vs ==
This is one of Python's most misunderstood distinctions.
==checks value equality — do the objects hold the same data?ischecks identity — are they the exact same object in memory?
This is called aliasing — two names pointing to the same mutable object. It is a common source of bugs. Always use == to compare values. Reserve is for checking None (if x is None).
Integer Caching — A CPython Optimization
CPython pre-creates integer objects for small integers (-5 to 256) and reuses them. This is why a is b is True for small numbers but False for large ones — it's a performance optimization, not part of the language spec. You should never rely on this behavior.
Reference Counting and Garbage Collection
Python tracks how many names (references) point to each object. When the count hits zero, the object is freed. You can inspect this with sys.getrefcount() — it reports one higher than you expect because the function call itself creates a temporary reference.
All Numeric Types in Depth
int — Arbitrary Precision Integers
Python's int is not a fixed 32-bit or 64-bit integer like in C or Java. It grows to hold any value you need, limited only by available RAM. Python never has integer overflow.
Bitwise operations work on integers — critical for flags, masks, and systems programming:
float — IEEE 754 Double Precision
Python floats are 64-bit IEEE 754 doubles. They give 15-17 significant decimal digits of precision, but cannot represent all decimal fractions exactly. Understanding this prevents nasty bugs.
When you need exact decimal arithmetic — money, accounting — use the decimal module:
complex — Complex Numbers Built In
Python has first-class complex number support. The j suffix (not i) marks the imaginary part.
bool — A Subclass of int
bool is literally a subclass of int. True equals 1 and False equals 0. This has surprising practical implications.
Short-circuit evaluation is essential to understand — Python stops evaluating and/or the moment the result is known:
Strings — A Complete Deep Dive
Immutability and Why It Matters
Strings in Python are immutable — once created, they cannot be modified. Any "modification" operation creates and returns a new string object. This enables safe sharing (two names can point to the same string with no aliasing issues) and allows strings to be hashable (usable as dictionary keys).
Indexing, Slicing, and Step
All Important String Methods
f-String Format Specifications
f-strings support a powerful mini-language. The syntax is {value:format_spec} where format_spec follows [[fill]align][sign][#][0][width][grouping][.precision][type].
Raw Strings, Multiline, and String Interning
None, type(), isinstance(), and Type Coercion
Control Flow — Deep Dive
Conditionals, Ternary, and Chained Comparisons
for Loops — Every Pattern You Need
while Loops, break, continue, and the else Clause
The else clause on a loop is Python's most misunderstood feature. It runs when the loop finishes without hitting a break. This is incredibly useful for "search and report not-found" patterns.
match/case — Structural Pattern Matching (Python 3.10+)
match/case is far more powerful than a simple switch statement. It performs structural pattern matching — it can match on object types, destructure sequences, match dict keys, and add guards.
Input and Output
Project: Grade Analyzer
This project brings together everything from this lesson: numeric operations, string formatting, control flow, and Python's data model. It reads a list of student scores and produces a comprehensive report.
Exercises
These exercises reinforce everything covered in this lesson. Each one builds a real, useful piece of functionality.
Exercise 1 — Memory Model (Easy)
Task: Predict and verify the output. For each pair of variables, predict whether is will be True or False, then run it to verify.
Exercise 2 — Float Precision (Easy)
Task: Write a function safe_equals(a, b, tol=1e-9) that compares two floats within a tolerance. Then verify the classic floating-point puzzles.
Exercise 3 — String Processing (Medium)
Task: Write a function title_stats(text) that takes a string of text and returns a formatted report showing: word count, unique words, most common word, longest word, and the text reversed word-by-word.
Exercise 4 — Type Coercion and Validation (Medium)
Task: Write a safe_convert(value, target_type, default=None) function that tries to convert value to target_type, returning default if the conversion fails.
Exercise 5 — Control Flow: FizzBuzz Enhanced (Medium)
Task: Write an enhanced FizzBuzz that handles arbitrary rules passed as a list of (divisor, word) tuples.
Exercise 6 — Numeric Patterns (Medium)
Task: Write functions to check if a number is a perfect number, an Armstrong number, and to find all such numbers up to a limit.
Exercise 7 — Pattern Matching (Hard)
Task: Use match/case to write a parse_command(cmd) function for a simple calculator REPL that handles commands like "add 5 3", "multiply 4 7", "help", and "quit".
Exercise 8 — BMI Calculator (Hard)
Task: Build a complete BMI calculator that accepts weight and height in multiple unit systems, validates input, computes BMI, and generates a detailed health report.
Excellent work. You now understand Python at a level that most developers never reach — the memory model, the full type system, and every control flow pattern. In the next lesson we go deeper into functions, scope, closures, and functional programming.