Python basics: variables, collections, loops and functions
Write small Python programs with variables, the core data types, lists, tuples, sets and dictionaries, conditionals, loops, functions and imports, and explain why each fact should live in one place.
Words in this lessonVariable · Data type · List · Dictionary · Function · Scope · Module (Python)
- Variable
- A name you attach to a value so you can use it later. Like the price tag on a bakery tray: change the tag once and everyone who reads it sees the new price.
- Data type
- The kind of value something is, such as text, a whole number or true/false. Like measuring flour by weight and eggs by count: you cannot add a kilo to a dozen.
- List
- An ordered collection of values that you can add to, remove from and change. Like the ticket rail in a kitchen: orders in sequence, and you can add or pull tickets.
- Dictionary
- A collection that maps names (keys) to values, so you can look things up by name. Like the menu board: find the item name, read its price.
- Function
- A named, reusable block of code that takes inputs and gives back a result. Like a recipe card: written once, followed by anyone, with different ingredients each time.
- Scope
- The part of a program where a name can be seen and used. Like the pastry kitchen's bowls: they stay in the pastry kitchen, and only the finished cake comes out.
- Module (Python)
- A Python file whose code you can borrow and reuse in another file. Like a recipe binder on the shelf: you borrow the recipe instead of rewriting it.
On this page
- How to run the examples
- Arjun's first attempt: six copies of the same sum
- Name tags on trays: variables
- What kind of thing is it? Data types
- Strings: the raw material of AI apps
- Numbers, and why money is tricky
- Booleans: yes or no
- Converting between types
- Four ways to hold many things
- Lists: ordered and changeable
- Tuples: ordered and fixed
- Sets: unique values only
- Dictionaries: look things up by name
- Following Ananya's order through the program
- Deciding: if, elif, else
- Repeating: for and while
- Recipe cards: functions
- Parameters with defaults
- `return` is not `print`
- What stays in the kitchen: scope
- Borrowing recipe binders: imports and modules
- Where it breaks
- Arjun explains it to Meera
- Try it yourself
- Common mistakes
- Recap
- Go deeper
It’s four days before Diwali, and the FC Road store of Crumb & Co. is drowning in phone pre-orders. The store manager has written six of them on a notebook page and sent a photo to Meera, Crumb’s founder: who ordered what, and nothing else. Each customer needs a total by this evening, including the delivery fee. The rule: free delivery for orders of ₹1,000 or more, ₹30 for ₹500 or more, and ₹60 for anything smaller.
Meera forwards the photo to Arjun, the backend developer who joined Crumb’s new AI team last week. “You’re the programmer. Can Python do this before 5 p.m.?”
Arjun writes JavaScript all day. He did some Python in college, and he’s forgotten most of it. But how hard can six sums be?
Priya, the senior AI engineer who is mentoring him, watches from the next desk. She has a plan: let him try, then use whatever goes wrong to teach him the Python he’ll need for every AI tool in this course. The Claude and OpenAI libraries, Hugging Face, PyTorch and LangGraph all speak Python first.
Important
The idea in one sentence: Python programs are built from a handful of pieces: variables that put names on values, collections that hold many values, conditionals and loops that decide and repeat, and functions that package steps so you write them once and reuse them everywhere.
How to run the examples
Every example in this module is a complete program you can run. Save the code in a file, for example orders.py, then run it from your terminal (the text window where you type commands):
python3 orders.py
If you’ve already installed uv (a fast tool that manages Python projects; we set it up properly in the files and environments lesson), uv run orders.py works too. You can also type python3 on its own to open the REPL (Read, Evaluate, Print, Loop): an interactive prompt marked >>> where each line runs as soon as you press Enter. It’s perfect for quick experiments. Type exit() to leave.
Below each example you’ll see the exact output it prints, so you can check yours.
Arjun’s first attempt: six copies of the same sum
Arjun opens a file and types what feels natural: one line per order, with the prices typed straight in.
# Arjun's first attempt. Don't copy this one.
total1 = 2 * 80 + 1 * 450 # Ananya: 2 croissants, 1 plum cake
total2 = 3 * 120 + 4 * 80 # Rohan: 3 baguettes, 4 croissants
total3 = 1 * 450 + 6 * 90 # Kabir: 1 plum cake, 6 brownies
print("Ananya owes: " + total1)
Python refuses to run the last line:
TypeError: can only concatenate str (not "int") to str
He doesn’t know it yet, but two separate problems are hiding here. He fixes the first by guessing (str(total1)), finishes all six orders by hand, adds the delivery fees in his head, and sends the numbers to Meera at 3 p.m.
At 3:20 she replies: “Sorry, forgot to say: croissants went up to ₹85 this morning.” Arjun now has to hunt through his file for every 80 that means “croissant”. He changes four of them. He misses one. He also changes an 80 that wasn’t a croissant at all. Two customers get the wrong total.
Priya rolls her chair over. “The sums were never the hard part. The problem is that the price lives in nine places, and the rule for delivery lives in your head. Let’s put each fact in exactly one place.”
Name tags on trays: variables
“Look at the display counter,” Priya says. “Every tray has a little tag: ‘Croissant, ₹85’. When the price changes, what do they change, the croissants or the tag?”
“The tag.”
“Right. A variable is a name tag you stick on a value so you can refer to it later. Change the tag once, and everything that reads it sees the new value.”
croissant_price = 85
plum_cake_price = 450
ananya_total = 2 * croissant_price + 1 * plum_cake_price
print(ananya_total)
croissant_price = 90 # move the tag to a new value
print(croissant_price)
620
90
The = sign means “stick this name on this value”. It’s not “equals” in the maths sense, which is why price = price + 10 is perfectly sensible in Python: take the current value, add 10, and move the tag to the result.
Notice also that ananya_total stayed at 620 even after the croissant price changed. The calculation ran once, with the values at that moment. A variable doesn’t remember how it was calculated, only the value it ended up with.
Variable names use lowercase words joined by underscores (order_total, not OrderTotal). This style is called snake_case, and almost all Python code follows it.
What kind of thing is it? Data types
“Now, your TypeError,” Priya says. “Flour is measured by weight, eggs by count, and the ‘contains nuts’ label is yes or no. You can’t add a kilo of flour to ‘yes’. Python is the same.”
Every value has a data type: the kind of value it is, which decides what you can do with it. The ones you’ll use every day:
| Type | What it holds | Example |
|---|---|---|
str |
Text, called a string of characters | "Eggless chocolate cake" |
int |
Whole numbers | 6 |
float |
Numbers with a decimal point | 4.5 |
bool |
True or False |
True |
NoneType |
Only the value None, meaning “nothing here” |
None |
print(type("Plum cake"))
print(type(6))
print(type(4.5))
print(type(False))
print(type(None))
<class 'str'>
<class 'int'>
<class 'float'>
<class 'bool'>
<class 'NoneType'>
Arjun’s line "Ananya owes: " + total1 tried to join a str and an int. For text, + means “glue together”. For numbers, it means “add”. Python won’t guess which one you meant, so it stops. That’s a feature, not an annoyance: JavaScript would quietly glue them and carry on.
Strings: the raw material of AI apps
Every prompt you send to a large language model (an LLM, the kind of AI behind Claude and ChatGPT) is a string, and so is every answer it sends back. You’ll spend a lot of time building and cleaning text.
customer = " Ananya "
item = "Diwali hamper"
qty = 2
clean_name = customer.strip() # remove spaces at both ends
print(clean_name.upper())
print(len(item)) # number of characters
print("hamper" in item) # does the text contain "hamper"?
print(item.replace("Diwali", "Festive"))
message = f"Hi {clean_name}, your {qty} x {item} are on the way!"
print(message)
ANANYA
13
True
Festive hamper
Hi Ananya, your 2 x Diwali hamper are on the way!
The last one is an f-string (formatted string): put an f before the opening quote, and anything inside { } is replaced by its value, converted to text for you. This is the clean fix for Arjun’s error. It’s also exactly how most prompts are built in real AI apps: a template with values dropped in.
Numbers, and why money is tricky
total = 450
people = 4
print(total / people) # true division: always gives a float
print(total // people) # floor division: the whole part only
print(total % people) # remainder, called "modulo"
print(round(112.456, 2))
print(0.1 + 0.2)
112.5
112
2
112.46
0.30000000000000004
That last line surprises everyone once. It isn’t a Python bug. Computers store decimals in binary, and some, like 0.1, can’t be stored exactly, the same way 1/3 can’t be written exactly in decimal (0.3333…). For money, store whole paise as int (₹80.50 becomes 8050), or use Python’s decimal module. Crumb’s prices are whole rupees, so int is fine here.
Booleans: yes or no
Comparisons produce booleans, and and, or and not combine them. This is how the delivery rule will be written.
subtotal = 610
is_member = False
print(subtotal >= 500) # greater than or equal
print(subtotal == 610) # == compares; = assigns
print(subtotal != 610) # != means "not equal"
print(subtotal >= 500 and is_member) # both must be True
print(subtotal >= 500 or is_member) # at least one must be True
print(not is_member)
True
True
False
False
True
True
Converting between types
Text from users, files and the web usually arrives as str, even when it looks like a number. A WhatsApp message that says “3” is the string "3", not the number 3. Convert before doing maths:
qty = int("3")
print(qty * 85)
print("Order #" + str(1042))
print(float("4.5"))
255
Order #1042
4.5
Four ways to hold many things
“Six orders means six of everything,” Priya says. “Six names, six carts. You don’t want total1 to total6. You want one name for the whole tray.” Python has four built-in collections, and each matches something on the bakery floor:
- A list is the ticket rail in the kitchen: orders in sequence, and you can add, remove or reorder them.
- A tuple is a printed receipt: an ordered record that never changes once printed.
- A set is a guest list: each name counts once, however many times it’s written.
- A dictionary is the menu board: look up a name, get its price.
Lists: ordered and changeable
rail = ["croissant", "plum cake", "baguette"]
print(rail[0]) # positions start at 0, not 1
print(rail[-1]) # negative positions count from the end
rail.append("brownie") # add to the end
print(rail)
print(len(rail))
print(rail[1:3]) # a "slice": positions 1 and 2, stopping before 3
print("baguette" in rail)
croissant
baguette
['croissant', 'plum cake', 'baguette', 'brownie']
4
['plum cake', 'baguette']
True
Tuples: ordered and fixed
line = ("croissant", 2) # one line of an order: (item, quantity)
item, qty = line # "unpacking" into two variables at once
print(item)
print(qty)
croissant
2
A cart is a list of these (item, qty) tuples. Tuples suit small records that shouldn’t change by accident, and functions use them to hand back two or three values at once.
Sets: unique values only
pickups = ["Baner", "FC Road", "Baner", "Kothrud", "FC Road"]
stores = set(pickups)
print(len(stores))
print("Kothrud" in stores)
3
True
A set drops duplicates and forgets order. Checking in on a set is very fast, even with millions of items, which is why sets are used to remember “IDs we’ve already processed”.
Dictionaries: look things up by name
This is the cure for Arjun’s nine copies of the croissant price.
menu = {
"croissant": 85,
"plum cake": 450,
"baguette": 120,
"brownie": 90,
}
print(menu["plum cake"]) # look up a value by its key
menu["kaju katli"] = 650 # add a new entry
menu["croissant"] = 80 # change an existing one
print(menu.get("donut")) # .get gives None instead of crashing
print(menu.get("donut", 0)) # ...or a default you choose
for item, price in menu.items(): # loop over key-value pairs
print(f"{item}: ₹{price}")
450
None
0
croissant: ₹80
plum cake: ₹450
baguette: ₹120
brownie: ₹90
kaju katli: ₹650
The name on the left of each pair is the key; what it points to is the value. Keys are unique, and dictionaries keep the order you added things.
| Collection | Looks like | Ordered? | Changeable? | Duplicates? | Typical use |
|---|---|---|---|---|---|
list |
[1, 2] |
Yes | Yes | Yes | Orders, chat messages, search results |
tuple |
(1, 2) |
Yes | No | Yes | Small fixed records, returning several values |
set |
{1, 2} |
No | Yes | No | Unique items, fast “have we seen this?” checks |
dict |
{"a": 1} |
Yes | Yes | Keys: no | Lookups by name, JSON-like records |
You’ll meet the dictionary everywhere in AI work. A conversation with an LLM is sent as a list of dictionaries, like [{"role": "user", "content": "Do you have eggless cakes?"}]. You’ll write that shape hundreds of times in this course.
Note
Pause and think: Arjun stores a cart as cart = [("croissant", 2), ("plum cake", 1)]. What does cart[1][0] give you? And why is the menu a dictionary but the cart a list?
Show the answer
cart[1] is the second tuple, ("plum cake", 1), and position 0 of that is "plum cake". Read chains of brackets left to right.
The menu is a dictionary because you look prices up by name: “what does a croissant cost?” The cart is a list because order and repetition matter: a customer could write “croissant” on two separate lines, and a dictionary would only keep one of them.
Following Ananya’s order through the program
Now Priya and Arjun write the real thing together. Before looking at the code, follow one order through it by hand. Ananya wants 2 croissants and 1 plum cake. The menu says croissants are ₹85 and plum cake is ₹450.
| Step | What happens | Values afterwards |
|---|---|---|
| 1 | Start with nothing | subtotal = 0 |
| 2 | First line of the cart: ("croissant", 2) |
item = "croissant", qty = 2 |
| 3 | Look up the price in the menu | menu["croissant"] is 85 |
| 4 | Multiply and add | 85 * 2 = 170, so subtotal = 170 |
| 5 | Second line: ("plum cake", 1) |
item = "plum cake", qty = 1 |
| 6 | Look up, multiply, add | 450 * 1 = 450, so subtotal = 620 |
| 7 | Delivery rule: is 620 ≥ 1000? | No |
| 8 | Is 620 ≥ 500? | Yes, so fee = 30 |
| 9 | Final total | 620 + 30 = 650 |
| 10 | Build the message | "Ananya: ₹650 (incl. ₹30 delivery)" |
Steps 2 to 6 repeat the same thing for every line: that’s a loop. Steps 7 and 8 choose between options: that’s a conditional. And the whole thing will run six times, once per customer: that’s a function, called six times. Let’s build each piece.
Deciding: if, elif, else
A delivery rider decides at each junction: left or right? if, elif (short for “else if”) and else let your code decide.
subtotal = 620
if subtotal >= 1000:
fee = 0
elif subtotal >= 500:
fee = 30
else:
fee = 60
print(f"Delivery fee: ₹{fee}")
Delivery fee: ₹30
Python checks the conditions top to bottom and runs the first block whose condition is True, then skips the rest. Order matters: if you checked >= 500 first, a ₹1,200 order would match it and wrongly pay ₹30.
Two details. Each condition ends with a colon :. And the lines that belong to it are indented by four spaces. In Python, indentation isn’t decoration. It’s how Python knows which lines belong to which block, the job { } braces do in JavaScript.
Repeating: for and while
for walks through a collection, one item at a time, running the indented block for each. Here’s steps 1 to 6 of the trace, as code:
menu = {"croissant": 85, "plum cake": 450, "baguette": 120, "brownie": 90}
cart = [("croissant", 2), ("plum cake", 1)]
subtotal = 0
for item, qty in cart: # unpack each (item, qty) tuple
line_total = menu[item] * qty
print(f"{qty} x {item} = ₹{line_total}")
subtotal = subtotal + line_total
print(f"Subtotal: ₹{subtotal}")
2 x croissant = ₹170
1 x plum cake = ₹450
Subtotal: ₹620
The same values as the hand trace, which is exactly the point of tracing by hand first. Three more loop tools you’ll see constantly:
for attempt in range(3): # range(3) gives 0, 1, 2
print("Attempt", attempt)
tickets = ["Late delivery", "Allergy question", "Refund"]
for number, ticket in enumerate(tickets, start=1): # a counter and the value together
print(number, ticket)
stock = 2
while stock > 0: # repeat as long as the condition is True
stock = stock - 1
print("Sold one, left:", stock)
Attempt 0
Attempt 1
Attempt 2
1 Late delivery
2 Allergy question
3 Refund
Sold one, left: 1
Sold one, left: 0
Inside any loop, break stops the loop early, and continue skips to the next item. Use while when you don’t know in advance how many times you’ll repeat (retrying until something succeeds, say), and for when you’re walking through a collection.
Recipe cards: functions
“Now,” Priya says, “you’re about to copy that loop six times. Don’t. What does the kitchen do with a recipe it makes every day?”
“Writes it on a card.”
“And then anyone can follow it with any ingredients. That’s a function: a named block of steps that takes inputs and hands back a result.”
def delivery_fee(subtotal):
"""Return the delivery fee for an order subtotal, in rupees."""
if subtotal >= 1000:
return 0
if subtotal >= 500:
return 30
return 60
def order_total(cart, menu):
"""Return (subtotal, fee, total) for a cart of (item, qty) tuples."""
subtotal = 0
for item, qty in cart:
subtotal = subtotal + menu[item] * qty
fee = delivery_fee(subtotal)
return subtotal, fee, subtotal + fee
menu = {"croissant": 85, "plum cake": 450, "baguette": 120, "brownie": 90}
print(order_total([("croissant", 2), ("plum cake", 1)], menu))
print(order_total([("baguette", 3), ("croissant", 4)], menu))
print(order_total([("plum cake", 1), ("brownie", 6)], menu))
(620, 30, 650)
(700, 30, 730)
(990, 30, 1020)
The new pieces:
defstarts a function, followed by its name and its parameters (the inputs it expects) in brackets.- The text in triple quotes is a docstring: a description for humans. Later in the course, LLMs will read docstrings too, to decide which of your functions to call.
returnends the function and sends a value back to whoever called it.return subtotal, fee, subtotal + feesends back a tuple of three values.- A function can call another function:
order_totalcallsdelivery_fee.
Look at Kabir’s order (the third line): ₹990, ten rupees short of free delivery. That’s the kind of fact Meera loves. (“Tell him one more brownie gets him free delivery!”)
Parameters with defaults
Give a parameter a default value and callers can leave it out:
def line_total(price, qty, discount=0.0):
"""Price for one line of an order after a discount (0.1 means 10% off)."""
return round(price * qty * (1 - discount), 2)
print(line_total(85, 2))
print(line_total(450, 1, discount=0.1))
170.0
405.0
return is not print
This trips up almost every beginner, so it gets its own section.
def total_with_print(price, qty):
print(price * qty) # shows the value, hands back nothing
def total_with_return(price, qty):
return price * qty # hands the value back
a = total_with_print(85, 2)
b = total_with_return(85, 2)
print("a is", a)
print("b is", b)
170
a is None
b is 170
print shows a value on your screen and forgets it. return hands it back so the rest of the program can use it. A function with no return hands back None. If a value is mysteriously None when you expected a number, a missing return is the first thing to check.
Note
Pause and think: Arjun writes fee = delivery_fee(subtotal) but his delivery_fee function uses print(30) instead of return 30. The screen shows 30, which looks right. What goes wrong on the very next line, total = subtotal + fee?
Show the answer
fee is None, because the function printed 30 but returned nothing. Then subtotal + fee tries to add an int and None, and Python stops with TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'. The printed 30 was a red herring: it came from inside the function and never reached fee.
What stays in the kitchen: scope
Arjun tries to print subtotal after calling order_total, outside the function, and gets an error. Priya explains with the kitchen again. “The pastry kitchen has its own bowls. When the pastry chef finishes, those bowls don’t appear on the front counter. Only the finished cake comes out.”
Variables created inside a function are local: they exist only while that function runs. Which names are visible where is called scope.
tax_rate = 0.05 # global: defined at the top level of the file
def price_with_tax(price):
tax = price * tax_rate # can READ the global
return price + tax # tax is local to this function
print(price_with_tax(100))
try:
print(tax) # tax only existed inside the function
except NameError as error:
print("Error:", error)
105.0
Error: name 'tax' is not defined
(The try and except let us show the error without the program stopping. You’ll learn them properly in the errors lesson.)
This is a feature. Because each function keeps its own bowls, order_total can use a variable called subtotal without worrying that some other function also has one. The rule of thumb: pass values in as parameters and send results out with return. A function that quietly changes global variables is hard to test, because its result depends on things you can’t see in its call.
Borrowing recipe binders: imports and modules
Crumb’s kitchen doesn’t invent every recipe. There’s a shelf of binders, and you borrow from them. In Python, a module is a file of code you can borrow from with import. Python comes with a large standard library of modules, and you can install thousands more.
import math
from datetime import date
print(math.ceil(7 / 3)) # round UP: boxes for 7 cakes, 3 per box
print(date(2026, 11, 8).strftime("%A")) # which weekday is Diwali 2026?
3
Sunday
import math brings in the whole module, and you use its contents as math.ceil. from datetime import date brings in one name directly.
Your own files are modules too. Arjun moves the menu and the two functions into crumb_utils.py:
# crumb_utils.py
MENU = {"croissant": 85, "plum cake": 450, "baguette": 120, "brownie": 90}
def delivery_fee(subtotal):
if subtotal >= 1000:
return 0
if subtotal >= 500:
return 30
return 60
def order_total(cart, menu=MENU):
subtotal = 0
for item, qty in cart:
subtotal = subtotal + menu[item] * qty
fee = delivery_fee(subtotal)
return subtotal, fee, subtotal + fee
Then a second file in the same folder uses it:
# preorders.py
from crumb_utils import order_total
preorders = [
("Ananya", [("croissant", 2), ("plum cake", 1)]),
("Rohan", [("baguette", 3), ("croissant", 4)]),
("Kabir", [("plum cake", 1), ("brownie", 6)]),
]
for name, cart in preorders:
subtotal, fee, total = order_total(cart)
print(f"{name}: ₹{total} (incl. ₹{fee} delivery)")
Ananya: ₹650 (incl. ₹30 delivery)
Rohan: ₹730 (incl. ₹30 delivery)
Kabir: ₹1020 (incl. ₹30 delivery)
MENU is in capitals as a signal to other programmers: “this is a setting; don’t change it while the program runs”. Packages you install, like anthropic or pandas, are imported in exactly the same way. Later in the course, you’ll organise AI apps as folders of modules: one for prompts, one for model calls, one for data.
Where it breaks
At 4:10 p.m., Meera sends one more message: “Also, a seventh order came in: Diya, 2 donuts and a plum cake.” Arjun adds it and runs the script. It stops with:
KeyError: 'donut'
Crumb doesn’t sell donuts; the store manager meant brownies. menu[item] crashes when the key doesn’t exist. That crash is actually useful: it’s better than silently charging ₹0 for donuts. But it stopped all seven orders, not only Diya’s. Two ways to handle it: check first with if item not in menu:, or use menu.get(item) and deal with the None. You’ll practise the first in the exercise below, and learn the full toolkit in the errors lesson.
Other things that break beginners’ programs, which experienced engineers watch for:
- Money in floats.
0.1 + 0.2isn’t0.3. Totals that are off by a paisa after thousands of orders come from this. Use whole numbers of paise, ordecimal. - Text that looks like a number. A quantity typed into WhatsApp is
"2", not2."2" * 85doesn’t fail; it gives you"2"repeated 85 times. Convert withint()at the point where data comes in. - Silent wrong answers from order. Putting
elif subtotal >= 500aboveif subtotal >= 1000gives every big order a ₹30 fee, with no error at all. Bugs that don’t crash are the expensive ones; test with a value in each range.
Arjun explains it to Meera
At 4:45, the seven totals go out, all correct. Meera stops by. “So what changed between your first try and this one?”
“Before, the croissant price was typed in nine places, and the delivery rule was in my head,” Arjun says. “Now the menu is a dictionary: one place, item name to price. Each order is a list of lines. A loop walks the lines and adds them up. The delivery rule is an if statement, written once. And the whole recipe is a function I call once per customer.”
“And if croissants go up again?”
“I change one number. Every total updates.”
Meera nods. “That’s the first thing you’ve said that I’d pay for.”
Try it yourself
Write order_total(cart, menu, loyalty_member=False) that:
- Skips any item not on the menu, printing a warning (this fixes Diya’s donuts).
- Gives loyalty members 10% off the subtotal.
- Returns the subtotal after any discount (no delivery fee this time).
Test it with:
menu = {"croissant": 85, "plum cake": 450, "baguette": 120}
cart = [("croissant", 2), ("donut", 1), ("plum cake", 1)]
Expected: a warning about donut, then 558.0 for a member and 620 for a non-member.
Show the answer
def order_total(cart, menu, loyalty_member=False):
"""Total a cart. Members get 10% off. Unknown items are skipped."""
subtotal = 0
for item, qty in cart:
if item not in menu:
print(f"Warning: {item} is not on the menu, skipping")
continue
subtotal = subtotal + menu[item] * qty
if loyalty_member:
return round(subtotal * 0.9, 2)
return subtotal
menu = {"croissant": 85, "plum cake": 450, "baguette": 120}
cart = [("croissant", 2), ("donut", 1), ("plum cake", 1)]
print(order_total(cart, menu, loyalty_member=True))
print(order_total(cart, menu))
Warning: donut is not on the menu, skipping
558.0
Warning: donut is not on the menu, skipping
620
Notice the member total is a float (because of * 0.9) and the other is an int. Small type details like this matter when you later save results to a database or send them to an API.
Common mistakes
- Using
=when you mean==.=assigns,==compares.if price = 85:is a syntax error. - Mixed or missing indentation. Python decides what’s inside an
if, loop or function by indentation alone. Use four spaces, and let your editor insert them. - Counting from 1. The first item of a list is
rail[0], and on a 3-item list,rail[3]is anIndexError. - Forgetting the colon.
if,elif,else,for,whileanddeflines all end with:. - Using
dict[key]for keys that might be missing. It raisesKeyError. Use.get(key, default)when a missing key is normal, anddict[key]when it would be a real bug you want to hear about. - Shadowing built-in names. Calling a variable
list,dict,sumortypehides Python’s own version, and code later in the file breaks in confusing ways.
Recap
- A variable is a name tag on a value; change the value in one place and everything that reads the name sees it.
- The everyday types are
str,int,float,boolandNone; Python won’t mix them silently, and f-strings are how you build text (and prompts) from values. - Lists are ordered and changeable, tuples are fixed records, sets keep unique items, and dictionaries look values up by key. AI chats are lists of dictionaries.
if/elif/elsedecide,forandwhilerepeat, and indentation shows what belongs to what.- Functions take parameters and
returna result; variables inside them are local;printis notreturn. importborrows code from modules: Python’s standard library, installed packages, or your own files.
That evening, Priya pulls up a real order from Crumb’s online shop to show Arjun what’s coming. It isn’t a tidy tuple. It’s a dictionary with a customer inside it, a list of items inside that, and a delivery slot that says null. “The phone orders were the easy version,” she says. “Next, let’s handle real data the Pythonic way.”
Go deeper
- The official Python tutorial: chapters 3 to 6 cover everything in this lesson in more depth.
- uv documentation, for when you’re ready to set up projects properly.