Tuples & Sets
Immutable sequences and unique collections — tuples, unpacking, tuple as dict keys, and sets.
OK, I think I can guess — a tuple is like a list but you can't change it? I remember seeing parentheses instead of brackets somewhere.
Exactly right. You're already further along than you think. A tuple uses parentheses and is immutable — once you create it, it's locked in:
point = (3, 7)
colors = ("red", "green", "blue")
singleton = (42,) # Note the trailing comma for a single-element tuple
Try to modify it and Python stops you cold:
point = (3, 7)
point[0] = 5 # TypeError: 'tuple' object does not support item assignment
If I can't change them... why not just use a list every time?
Because sometimes "you can't change this" is exactly what you want. Think of it like protecting a cell in your spreadsheet — you lock it so nobody accidentally overwrites the formula. Tuples give you that guarantee in code. They're also faster than lists, and — this is the big one — they can be used as dictionary keys. Lists can't.
But first, the most useful thing about tuples: unpacking.
point = (3, 7)
x, y = point
print(x) # 3
print(y) # 7
# Works with any number of elements
name, age, city = ("Alice", 30, "NYC")
One line, and each value lands in its own variable. You've actually been doing this already without realizing it — every time you wrote for key, value in dict.items(), Python was unpacking tuples behind the scenes.
Wait, seriously? That .items() loop was using tuples the whole time?
The whole time. .items() returns pairs like ("name", "Alice"), and for key, value in ... unpacks each one. Now you know what's actually happening under the hood.
And tuples as dictionary keys — when would I need that?
Anytime you want to look something up by a combination of values. Like a coordinate pair, or a student's score in a specific subject:
# Grid of values indexed by (row, col)
grid = {}
grid[(0, 0)] = "start"
grid[(0, 1)] = "wall"
grid[(1, 0)] = "path"
print(grid[(0, 0)]) # "start"
# Student scores indexed by (name, subject)
scores = {}
scores[("Alice", "math")] = 92
scores[("Alice", "science")] = 88
scores[("Bob", "math")] = 75
print(scores[("Alice", "math")]) # 92
Try that with a list and Python crashes: {[0, 0]: "start"} raises a TypeError. Lists are mutable, so Python can't use them as keys.
OK, tuples feel like "lists you can trust." What about sets?
A set is an unordered collection of unique elements. Throw duplicates at it — Python doesn't care, it keeps one of each:
colors = {"red", "blue", "green", "red", "blue"}
print(colors) # {"red", "blue", "green"} — duplicates gone
print(len(colors)) # 3
Curly braces, like dictionaries — but no key-value pairs. One gotcha: {} creates an empty dict, not an empty set. Use set() for that:
empty_set = set() # Correct
empty_dict = {} # This is a dict, not a set!
So if I have a customer list with duplicate emails from our CRM export, I could just... set() it?
Exactly. That's one of the most common uses:
# Remove duplicates from a list
names = ["Alice", "Bob", "Alice", "Charlie", "Bob"]
unique_names = list(set(names))
print(unique_names) # ["Alice", "Bob", "Charlie"] (order may vary)
And checking whether something is in a set is dramatically faster than checking a list — especially when you have thousands of items:
# Fast membership testing
valid_codes = {"A1", "B2", "C3", "D4"}
user_code = "B2"
if user_code in valid_codes:
print("Valid!")
You can add and remove elements too:
tags = {"python", "beginner"}
tags.add("tutorial")
tags.discard("beginner") # Safe remove — no error if missing
print(tags) # {"python", "tutorial"}
.add() inserts, .discard() removes safely, .remove() removes but raises KeyError if the element isn't there.
Two new tools in your toolkit. Tuples for data you trust. Sets for data you need unique. Let's put them together.
Practice your skills
Sign up to write and run code in this lesson.
Tuples & Sets
Immutable sequences and unique collections — tuples, unpacking, tuple as dict keys, and sets.
OK, I think I can guess — a tuple is like a list but you can't change it? I remember seeing parentheses instead of brackets somewhere.
Exactly right. You're already further along than you think. A tuple uses parentheses and is immutable — once you create it, it's locked in:
point = (3, 7)
colors = ("red", "green", "blue")
singleton = (42,) # Note the trailing comma for a single-element tuple
Try to modify it and Python stops you cold:
point = (3, 7)
point[0] = 5 # TypeError: 'tuple' object does not support item assignment
If I can't change them... why not just use a list every time?
Because sometimes "you can't change this" is exactly what you want. Think of it like protecting a cell in your spreadsheet — you lock it so nobody accidentally overwrites the formula. Tuples give you that guarantee in code. They're also faster than lists, and — this is the big one — they can be used as dictionary keys. Lists can't.
But first, the most useful thing about tuples: unpacking.
point = (3, 7)
x, y = point
print(x) # 3
print(y) # 7
# Works with any number of elements
name, age, city = ("Alice", 30, "NYC")
One line, and each value lands in its own variable. You've actually been doing this already without realizing it — every time you wrote for key, value in dict.items(), Python was unpacking tuples behind the scenes.
Wait, seriously? That .items() loop was using tuples the whole time?
The whole time. .items() returns pairs like ("name", "Alice"), and for key, value in ... unpacks each one. Now you know what's actually happening under the hood.
And tuples as dictionary keys — when would I need that?
Anytime you want to look something up by a combination of values. Like a coordinate pair, or a student's score in a specific subject:
# Grid of values indexed by (row, col)
grid = {}
grid[(0, 0)] = "start"
grid[(0, 1)] = "wall"
grid[(1, 0)] = "path"
print(grid[(0, 0)]) # "start"
# Student scores indexed by (name, subject)
scores = {}
scores[("Alice", "math")] = 92
scores[("Alice", "science")] = 88
scores[("Bob", "math")] = 75
print(scores[("Alice", "math")]) # 92
Try that with a list and Python crashes: {[0, 0]: "start"} raises a TypeError. Lists are mutable, so Python can't use them as keys.
OK, tuples feel like "lists you can trust." What about sets?
A set is an unordered collection of unique elements. Throw duplicates at it — Python doesn't care, it keeps one of each:
colors = {"red", "blue", "green", "red", "blue"}
print(colors) # {"red", "blue", "green"} — duplicates gone
print(len(colors)) # 3
Curly braces, like dictionaries — but no key-value pairs. One gotcha: {} creates an empty dict, not an empty set. Use set() for that:
empty_set = set() # Correct
empty_dict = {} # This is a dict, not a set!
So if I have a customer list with duplicate emails from our CRM export, I could just... set() it?
Exactly. That's one of the most common uses:
# Remove duplicates from a list
names = ["Alice", "Bob", "Alice", "Charlie", "Bob"]
unique_names = list(set(names))
print(unique_names) # ["Alice", "Bob", "Charlie"] (order may vary)
And checking whether something is in a set is dramatically faster than checking a list — especially when you have thousands of items:
# Fast membership testing
valid_codes = {"A1", "B2", "C3", "D4"}
user_code = "B2"
if user_code in valid_codes:
print("Valid!")
You can add and remove elements too:
tags = {"python", "beginner"}
tags.add("tutorial")
tags.discard("beginner") # Safe remove — no error if missing
print(tags) # {"python", "tutorial"}
.add() inserts, .discard() removes safely, .remove() removes but raises KeyError if the element isn't there.
Two new tools in your toolkit. Tuples for data you trust. Sets for data you need unique. Let's put them together.
Practice your skills
Sign up to write and run code in this lesson.