Pebellslearn by building
0%
RoadmapMatrixCatalogSandboxSign in
Fundamentals  ›  Lesson

Lists, Tuples & Sets

Lists, Tuples, Sets 16 minThe three built-in collections and when to use each
You're building a piece ofBill Splitter & Tip Calculator
This piece — unique_dishes(): The distinct dishes the table ordered (de-duplicated).
Scenario The table shouts orders and some dishes are repeated. The app needs a clean, alphabetised list of the distinct dishes ordered.
Your task
Build unique_dishes(orders). It takes a list of ordered dish names (with duplicates) and returns a sorted list of the unique names. Example: unique_dishes(["soup", "steak", "soup"]) → ["soup", "steak"] sorted → ["soup", "steak"].

Lists, Tuples & Sets

You've been using lists since Lesson 5. Now meet all three of Python's built-in collections — lists, tuples, and sets — and learn when each one fits. This lesson builds the app's order list: the distinct dishes a table ordered.

Every box is live — edit and ▶ Run.


Part 1 — Lists: ordered and changeable

A list holds items in order, in square brackets [ ]. It's the workhorse collection — use it whenever order matters and the contents may change:

python

Lists are mutable — you can change them after creating them:

python

Slicing grabs a range ([start:stop], stop not included):

python

Part 2 — Tuples: ordered and fixed

A tuple is like a list but immutable — once made, it can't change. Use a tuple for a fixed group of values that belong together (a coordinate, an RGB colour, a row):

python

Try to change it and Python stops you:

python

A handy trick is unpacking — pull a tuple's values into separate variables in one line:

python

Part 3 — Sets: unordered and unique

A set holds unique items with no order, in curly braces { }. Duplicates simply vanish — which makes sets perfect for "give me the distinct values":

python

❓ Cross-question — "Is a Python set like a JS Set?" Behaviour-wise yes (unique items, fast in). Two catches: the literal {} is an empty dict, not a set — an empty set must be set(). And set items must be hashable (immutable), whereas a JS Set can hold any object by reference.

Removing from a set: .remove() vs .discard()

Two methods that look interchangeable and are not. .remove() raises if the item isn't there; .discard() shrugs:

broken — fix itKeyError

Run it and meet KeyError. Then make it print the two orders without crashing.

Reach for .discard() when "it might not be there" is normal, and .remove() when its absence means something has already gone wrong and you'd rather hear about it.

Sets also do maths — union |, intersection &, difference -:

python

Which do I pick? Ordered list you'll change → list. Fixed group that shouldn't change → tuple. Just need the unique values / fast membership → set.


Part 4 — Combine them: unique, then sorted

Sets lose duplicates but also lose order. sorted(...) takes any collection and returns a tidy list in order. Chain them and you get "unique and sorted":

python

That single expression is exactly the task below.


Part 5 — Idioms & real-world patterns

The three collections have sharp edges that trip up developers from every other language. Slow down here — especially on copying.

Assignment shares — it does NOT copy

b = a does not make a second list. Both names point at the same list, so a change through one is visible through the other:

What does this print?
a = [1, 2, 3]
b = a
b.append(4)
print(len(a))
python

Step through it. Watch a change on the line that only mentions b — that's the whole lesson in one frame:

step through it
1a = [1, 2, 3]
2b = a
3b.append(4)
4copy = a.copy()
5copy.append(99)
6print(a, copy)

Coming from Java/JS: exactly like assigning an array/object reference — you copied the reference, not the data. Ints and strings only feel like copies because they're immutable.

❓ Cross-question — "So b = a is a reference copy, like JS objects/arrays?" Exactly — assignment never copies a list/dict/set; both names bind the same object (a is b). Numbers, strings, and tuples only look copied because they're immutable, so you can't observe the sharing. To truly copy, use .copy() / deepcopy below.

is vs == — identity vs value

== asks "same value?"; is asks "the same object?" Use == to compare, and is only for None:

python

Coming from Java: == here is .equals(); is is Java's == (reference identity). From JS: == ≈ value check, is=== on object identity.

Shallow copy — a real (but one-level) copy

To actually duplicate a list, use .copy(), list(...), or a full slice [:]:

python

⚡ Deep copy — copies all the way down

A shallow copy duplicates the outer list but still shares the inner objects. With nested data that's a classic bug — copy.deepcopy fixes it:

python

Coming from JS: cart.copy() is [...cart] / Object.assign (one level); copy.deepcopy(cart) is structuredClone(cart).

.extend vs +, and the other methods

python

Extended unpacking — a, *rest

Grab the first (or last) item and collect the rest with a starred name:

python

Sets: comprehensions, frozenset, and subset math

python

⚡ Advanced — hashability: why a list can't be a set item or dict key

Sets and dict keys must be hashable — which in practice means immutable. Tuples of immutables qualify; lists never do:

python

Coming from Java: same reason a mutable object makes a bad HashMap key — if it changes, its hash changes and the map breaks. Python refuses it up front.

❓ Cross-question — "Why can JS put any object in a Set/Map but Python can't?" JS keys by reference identity; Python keys by value hash, which requires the element be immutable (str, int, tuple, frozenset). That's why a list can't live in a set or be a dict key — its contents (and hash) could change under the collection.

⚡ Advanced — namedtuple: a tuple with named fields

When a tuple's positions start to blur, give them names (a lightweight, immutable record — the step before a full dataclass):

python

🎯 Your turn

Write unique_dishes(orders) — it takes a list of dish names (with duplicates) and returns a sorted list of the unique names:

  • unique_dishes(["soup", "steak", "soup", "salad"])["salad", "soup", "steak"]
  • unique_dishes([])[]

Hint — set(orders) drops the duplicates, and sorted(...) gives back an ordered list. Together: sorted(set(orders)).

Then press ▶ Run, tap the Live App try chips to call it with different orders, and hit ✓ Check. Green = this piece of the app is built. ✅

Practice — level up

0/5 solved

Solve each in its own editor — Run to try, Check to grade. Stuck? Reveal a Hint, or the full Solution + walkthrough.

Warm-upReverse a list

Write reverse(items) returning a new reversed list, using slice syntax (not .reverse()).

slicing
DrillHead and tail

Write head_tail(items) returning [first, rest_list] — the first item and a list of the rest. Empty list → [None, []]. Use star-unpacking.

star-unpackingguard
BuildDedupe, keep order

Write dedupe(items) returning the items with duplicates removed but original order preserved. Use a seen set.

setloop
BossList diff

Write diff(old, new) returning {"added": [...], "removed": [...], "common": [...]} — items only in new, only in old, and in both. Each list sorted ascending.

set-opssorteddict
CapstoneAnalyze numbers

Write analyze(nums) returning {"unique": [...], "duplicates": [...], "top": <max>} — sorted unique values, sorted values that appear more than once, and the largest. Empty → {"unique": [], "duplicates": [], "top": None}.

setcomprehensionmaxdict
unique_dishes.py
Call the function you wrote — just like your app's frontend would. Edit the inputs and hit Call.
unique_dishes(orders) → listThe de-duplicated, sorted list of dishes the table ordered.
try:
returned
Press Run to execute your code.
Press Check to run the tests for this lesson.
Lists, Tuples & Sets — Pebells