Notes: M2: Logic & data
In M1 your program ran top to bottom, doing the same thing every time. Real software is more interesting because it reacts: it looks at data and decides, and it handles many things without you writing the same line over and over. This module gives you the two powers that turn a script into a program, making decisions and looping over data: plus the two containers that hold almost all real-world data: the list and the dictionary. The dictionary in particular is your first direct bridge to the AI half of the course: it's the exact shape data arrives in from an API.
A note on difficulty: this module has more new pieces than M1 (comparisons,
if/elif/else, loops, lists, dictionaries). That's normal, and it's why the lab moves in tiny steps and splits into two parts. You do not need to memorize anything; you need to be able to read each line. Go slowly, run every cell, and lean on your partner.
Indentation: Python's most important whitespace
Before anything else, one rule that's new since M1. In Python, the spaces at the start of a
line are meaningful. The lines that belong "inside" an if or a for are pushed in, indented, by 4 spaces:
for score in scores:
print(score) # indented → INSIDE the loop, runs each time
print("done") # not indented → OUTSIDE the loop, runs once at the end
IndentationError. In Colab,
pressing Enter after a line ending in : usually indents for you. If in doubt, line your code up
with the examples.
Making decisions
Comparisons → True or False
A decision starts with a yes/no question. Comparison operators ask one and answer with a
boolean (True/False):
| Operator | Asks | 7 ? 5 |
|---|---|---|
== |
equal? | False |
!= |
not equal? | True |
> / < |
greater / less than? | True / False |
>= / <= |
at least / at most? | True / False |
=vs==is the classic trap. One=assigns (score = 82puts 82 intoscore). Two==compares (score == 82asks "are they equal?"). Using=where you meant==is a mistake everyone makes early.
if / elif / else
These run a block of code only when a condition is true:
if score >= 90:
grade = "A" # runs only if score >= 90
elif score >= 60:
grade = "Pass" # checked ONLY if the line above was False
else:
grade = "Resit" # runs if none of the above were True
True, then skips the
rest. elif ("else if") lets you list several options; else is the catch-all. You can have many
elifs, and elif/else are optional.
Combining questions: and, or, not
You can join conditions: and (both must be true), or (at least one), not (flips it).
if age >= 21 and money >= 5:
print("We're getting a drink!")
Repeating with loops
The for loop: once per item
A for loop walks through a collection, handing you one item at a time:
for score in scores: # score becomes 82, then 45, then 91, then 67
print(score)
for i in range(5): is a handy variant that counts 0,1,2,3,4 when you just need to do
something N times.
The while loop: until a condition changes
A while loop repeats as long as a condition stays true:
count = 0
while count < 5:
print(count)
count += 1 # MUST move toward stopping, or the loop never ends
count += 1 is shorthand for count = count + 1. Watch out: if the condition never becomes
false, you get an infinite loop (in Colab, press the ▦ stop button). Use for when you know the
items; use while when you're waiting for something to change.
The two containers
Lists: many things, in order
A list holds values in order, in [ ]. You reach items by position (an index),
starting at 0:
movies = ["Jaws", "Up", "Heat"]
movies[0] # "Jaws" (first)
movies[-1] # "Heat" (last)
movies[0:2] # ["Jaws", "Up"] (a slice: from 0 up to, but not including, 2)
len(movies) # 3
movies.append("Alien") # add to the end
append), and remove (pop) items. They're perfect
for "a bunch of the same kind of thing."
Dictionaries: labelled values
A dictionary stores "key": value pairs in { }. Instead of a position, each value has a
name (its key):
student = {"name": "Alice", "score": 91}
student["name"] # "Alice", look up by key
student["grade"] = "A" # add or change a key
del student["score"] # remove a key
len(student) # how many pairs
student["age"]) raises a KeyError; student.get("age") returns
None instead of erroring, which is safer when you're not sure. In modern Python, a dictionary
keeps its keys in the order you added them.
flowchart TB
subgraph List["LIST, reach by position"]
L0["[0] Jaws"] --- L1["[1] Up"] --- L2["[2] Heat"]
end
subgraph Dict["DICTIONARY, reach by name"]
K1["name → Alice"]
K2["score → 91"]
K3["grade → A"]
end
Lists of dictionaries: the shape of real data
Combine them and you get the single most common shape of real-world data: a list of dictionaries: many records, each with named fields.
expenses = [
{"item": "Coffee", "amount": 4.50},
{"item": "Groceries", "amount": 62.00},
]
Go deeper (optional, not needed for today's win)
- **Truthiness:** in an `if`, Python treats `0`, `""`, `[]`, `{}`, and `None` as "falsy" (like `False`), and most other values as "truthy". So `if my_list:` means "if the list isn't empty." - **`break` and `continue`:** inside a loop, `break` exits early; `continue` skips to the next item. - **Looping a dictionary:** `for key in student:` gives you the keys; `for key, value in student.items():` gives you both at once. - **Tuples** are like lists but **immutable** (can't change), written with `( )`, e.g. a coordinate `(40.71, -74.00)`. You'll meet them occasionally; lists and dicts cover most needs.Check yourself
Lock in today's win, answer each in your head, then reveal.
1. What's the difference between = and ==?
Show answer
= assigns: it puts a value into a variable (x = 5). == compares: it asks "are
these equal?" and gives back True or False (x == 5). Using = where you meant == is a
very common early mistake.
2. In if / elif / else, how many blocks run?
Show answer
Exactly one (or none, if there's no else). Python checks conditions top to bottom and runs
the first block whose condition is True, then skips all the rest.
3. You have scores = [82, 45, 91]. What is scores[0], and what is len(scores)?
Show answer
scores[0] is 82: indexing starts at 0, so position 0 is the first item. len(scores)
is 3: the number of items.
4. When would you use a dictionary instead of a list?
Show answer
Use a list when you have many of the same kind of thing and order/position matters. Use a
dictionary when each value has a name (a label), like a record with "name",
"amount", "date". Real-world data usually has names, which is why dictionaries are
everywhere, and why API replies arrive as dictionaries.
5. Why does this module say a dictionary is "the shape APIs speak"?
Show answer
Because when you call an AI model (M4), its reply comes back as a dictionary of
"key": value pairs, often a whole list of dictionaries. The same shape, written as text,
is JSON (M3). Knowing how to read a value by its key means you can already read an API
response.
New words (also in resources/glossary.md): comparison operator,
boolean expression, if / elif / else, condition, and / or / not, indentation, block,
for loop, while loop, iterate, range, list, index, slice, mutable, append, dictionary, key,
value, KeyError, tuple.
Source: original, written for this course. Concepts and worked examples (comparisons, if/
elif/else, for/while loops, lists, dictionaries) are informed by the instructor's own
Python_continuation.pdf notes in Material_AI_Engineering/; the budget-categorizer build is
original. No third-party text or figures; diagrams are original. (Note: that source calls
dictionaries "unordered"; modern Python (3.7+) keeps insertion order, which these notes reflect.)