Learning Goals
3 minBy the end of this lesson you can:
- Create a tuple with round brackets
( )and read items back by index. - Explain "immutable" in plain words and predict what crashes when you try to change a tuple.
- Pick between a list and a tuple based on whether the data should ever change.
Warm-Up
5 minThink of two real-world "collections":
- A shopping basket — items go in, items come out, the contents change every minute.
- Your date of birth — three numbers (day, month, year) that should never change once they're set.
Both are collections. But the second one shouldn't allow .append() at all — that's a bug waiting to happen. Today we'll see the tool Python gives us for "locked" data.
Predict the output:
birthday = (12, 8, 2014) print(birthday[0]) print(len(birthday))
Show the answer
12 3
Round brackets build a tuple. [0] indexing and len() work exactly like on a list.
A tuple is a list that has been welded shut. Same reading powers, no editing powers. Use it for data that should never change after it's created.
New Concept · The Tuple
14 minBuilding one
Use round brackets ( ) instead of square brackets:
point = (10, 20) birthday = (12, 8, 2014) colours = ("red", "green", "blue") empty = ()
Python also accepts a comma-only form — the brackets are optional when there's no ambiguity. These two lines are identical:
a = (1, 2, 3) b = 1, 2, 3 print(a == b) # → True
To make a tuple with one item, you need a lonely trailing comma — otherwise Python thinks the brackets are just grouping. Compare:
not_a_tuple = (5) # this is just the number 5 one_tuple = (5,) # this is a tuple of one item print(type(not_a_tuple)) # → <class 'int'> print(type(one_tuple)) # → <class 'tuple'>
Reading from a tuple
Everything you learned about reading lists also works on tuples:
birthday = (12, 8, 2014) print(birthday[0]) # → 12 (the day) print(birthday[-1]) # → 2014 (the year) print(len(birthday)) # → 3 for n in birthday: print(n)
What you can't do
Try any of these and Python crashes with TypeError: 'tuple' object does not support item assignment:
birthday = (12, 8, 2014) birthday[0] = 13 # ❌ can't reassign birthday.append(5) # ❌ no .append() birthday.remove(8) # ❌ no .remove() del birthday[0] # ❌ no del
The tuple is locked. To "change" it, you build a brand-new one:
birthday = (12, 8, 2014) birthday = (12, 8, 2015) # not edited — replaced print(birthday)
Why bother with locked data?
Three good reasons:
- Safety. If a value should never change — coordinates, RGB colours, dates of birth — using a tuple turns a sneaky bug into an immediate crash. Better a crash than wrong data.
- Speed. Tuples are a tiny bit faster than lists, because Python knows they can't grow.
- Talking shape. Functions love to return tuples to hand back several values at once. We'll see that in PY-L2-04.
List vs tuple — when to use which
Use a LIST when… Use a TUPLE when… - the contents will change - the data is fixed - you need .append() - the order/positions have meaning - it's "a bag of things" - it's "one combined value" (orders, students, tags) (a point, an RGB colour, a row)
Worked Example · Coordinates & Colours
12 minThe story
You're building a map of the school's sports day. Each event has a fixed location on the field (an x, y coordinate) and a fixed team colour (an R, G, B triple).
Locations and colours shouldn't change once the day starts — so we model them as tuples. The list of events, on the other hand, will grow as new ones are added — that's a list of tuples.
Save as sports_day.py:
Code
# sports_day.py — fixed coordinates and colours # Each event = (name, location-tuple, colour-tuple) events = [ ("100m Sprint", (50, 10), (255, 0, 0)), ("Long Jump", (80, 30), ( 0, 200, 0)), ("Tug of War", (10, 60), ( 0, 0, 255)), ] for name, loc, rgb in events: print(name) print(" Location:", loc) print(" Colour :", rgb) print()
Output
100m Sprint Location: (50, 10) Colour : (255, 0, 0) Long Jump Location: (80, 30) Colour : (0, 200, 0) Tug of War Location: (10, 60) Colour : (0, 0, 255)
What the loop is doing
That for name, loc, rgb in events line is doing two things at once:
- Walking through the list of events — like every
forloop. - Unpacking each three-item tuple into three named variables. We'll spend all of PY-L2-04 on unpacking — for now, just notice that we get three clean names instead of having to write
events[0][0],events[0][1], etc.
The locked-data demo
Add this at the bottom of the file and run it:
first_event = events[0] print(first_event) # Try to change the colour to yellow: first_event[2][0] = 255 # this changes the inner tuple? Let's see… # TypeError: 'tuple' object does not support item assignment
Python refuses. The colour is a tuple — locked. If we'd used a list [255, 0, 0] instead, the change would have gone through silently and our "red event" would be a different red on the next page. Better the crash.
Every "tuple object does not support item assignment" error is Python protecting you. Don't silence it with a try/except. Either the data should be a list (use one), or the change is wrong (don't make it).
Try It Yourself
13 minThree quick exercises. Type each one in a fresh file.
Create a tuple dob with your day, month and year as three numbers. Print the day on its own line, the month on its own line, the year on its own line, and the length of the tuple.
Hint
dob = (12, 8, 2014) print("Day :", dob[0]) print("Month:", dob[1]) print("Year :", dob[-1]) print("Items:", len(dob))
Take the same dob tuple. Add a line that tries to change the year to 2015 with dob[2] = 2015. Run it. Read the exact error message and copy the last line of the traceback into a Python comment at the bottom of the file.
Hint
dob = (12, 8, 2014) dob[2] = 2015 # TypeError: 'tuple' object does not support item assignment
Reading error messages out loud is one of the most useful programming habits you can build. The message tells you exactly what Python refused to do, and the line number tells you where.
Make two variables: a = (7) and b = (7,). Print type(a) and type(b). Explain in a comment why they're different.
Hint
a = (7) b = (7,) print(type(a)) # → <class 'int'> print(type(b)) # → <class 'tuple'> # Brackets alone don't make a tuple — only the comma does.
This is one of Python's most famous trip-wires. Forgetting the comma silently turns your "tuple of one" into just the value inside.
Mini-Challenge · The Constellations Atlas
8 minBuild atlas.py, a tiny star catalogue. Each star is a fixed bundle: name, brightness (a number 0–10) and colour. None of those should ever change after they're recorded — perfect for tuples.
Your file must:
- Start with a list of tuples, with at least four stars. Example:
("Sirius", 9, "blue-white"). - Loop through the list and print one line per star:
Sirius — brightness 9 — blue-white. - Use
len()to print the total number of stars at the end. - Print the brightest star's name. Hint: use a
forloop that tracksbestandbest_name— like the "biggest in a list" pattern you used in PY-L1-22.
Stretch goal. Attempt to change one star's brightness with stars[0][1] = 10. Catch the error in a comment, then explain why this protection is helpful.
Show one possible solution
# atlas.py — a tiny star catalogue using tuples stars = [ ("Sirius", 9, "blue-white"), ("Vega", 8, "white"), ("Antares", 7, "red"), ("Polaris", 6, "yellow-white"), ] print("The Atlas") print("---------") for name, brightness, colour in stars: print(name, "— brightness", brightness, "—", colour) print() print("Total stars:", len(stars)) # Find the brightest best = 0 best_name = "" for name, brightness, colour in stars: if brightness > best: best = brightness best_name = name print("Brightest :", best_name, "(", best, ")") # stars[0][1] = 10 # TypeError: 'tuple' object does not support item assignment # Good — the data is meant to be fixed. The crash protects us.
The non-negotiables are: a list of at least four 3-element tuples, the unpacking loop for name, brightness, colour in stars, a len() count, and a brightest-star scan. Your choice of stars and colours is yours.
Recap
3 minA tuple is an ordered collection like a list, but locked at creation. You build it with round brackets — or just commas — and you read from it with the same square-bracket indexing you already know. You can't append, remove or reassign items; Python crashes if you try. Use a tuple whenever the data shouldn't change: coordinates, colours, dates, anything that represents one combined value.
Vocabulary Card
- tuple
- An ordered, immutable collection. Built with round brackets:
(1, 2, 3). - immutable
- "Cannot be changed." A tuple, a string and a number are all immutable in Python.
- (5,)
- A tuple with exactly one item. The lonely comma is required —
(5)is just the number five.
Homework
4 minSave a new file my_three_things.py. Build a tuple called me that contains exactly three things about you that won't change this year: your full name, the year you were born, and your favourite primary-school subject.
Then:
- Print each item on its own line, with a label.
- Print
len(me)at the end. - Calculate and print your age as
2026 - year. - Add a final line that tries to change the second item to a different year. Run the file, copy the last line of the error into a comment underneath, then comment out the buggy line so the program runs cleanly.
Stretch. Make a list of three friends' me-style tuples — everyone = [me, friend1, friend2] — and loop through it, printing each person on three lines.
Sample · my_three_things.py
# my_three_things.py — locked facts about me me = ("Aiman bin Razif", 2014, "art") print("Name :", me[0]) print("Born :", me[1]) print("Subject:", me[2]) print("Items :", len(me)) print("Age :", 2026 - me[1]) # me[1] = 2015 # TypeError: 'tuple' object does not support item assignment # Stretch — a list of friends as tuples everyone = [ me, ("Aisyah binti Hassan", 2015, "maths"), ("Wei Jie Tan", 2014, "music"), ] print() for person in everyone: print("Name :", person[0]) print("Born :", person[1]) print("Subject:", person[2]) print()
Your three facts are personal — that's the point. The non-negotiables are: a three-item tuple, the four labelled prints, an age calculation that subtracts from 2026, and the commented-out crash line.