Tuples and Sets
Part 1: Tuples
What is a Tuple?
A tuple is essentially an immutable list. Once created, you cannot change its contents.
# List - mutable (can change)
L = [1, 2, 3]
L[0] = 100 # Works fine
# Tuple - immutable (cannot change)
t = (1, 2, 3)
t[0] = 100 # TypeError: 'tuple' object does not support item assignment
Creating Tuples
# With parentheses
t = (1, 2, 3)
# Without parentheses (comma makes it a tuple)
t = 1, 2, 3
# Single element tuple (comma is required!)
t = (1,) # This is a tuple
t = (1) # This is just an integer!
# Empty tuple
t = ()
t = tuple()
# From a list
t = tuple([1, 2, 3])
# From a string
t = tuple("hello") # ('h', 'e', 'l', 'l', 'o')
Common mistake:
# This is NOT a tuple
x = (5)
print(type(x)) # <class 'int'>
# This IS a tuple
x = (5,)
print(type(x)) # <class 'tuple'>
Accessing Tuple Elements
t = ('a', 'b', 'c', 'd', 'e')
# Indexing (same as lists)
print(t[0]) # 'a'
print(t[-1]) # 'e'
# Slicing
print(t[1:3]) # ('b', 'c')
print(t[:3]) # ('a', 'b', 'c')
print(t[2:]) # ('c', 'd', 'e')
# Length
print(len(t)) # 5
Why Use Tuples?
1. Faster and Less Memory
Tuples are more efficient than lists:
import sys
L = [1, 2, 3, 4, 5]
t = (1, 2, 3, 4, 5)
print(sys.getsizeof(L)) # 104 bytes
print(sys.getsizeof(t)) # 80 bytes (smaller!)
2. Safe - Data Cannot Be Changed
When you want to ensure data stays constant:
# RGB color that shouldn't change
RED = (255, 0, 0)
# RED[0] = 200 # Error! Can't modify
# Coordinates
location = (40.7128, -74.0060) # New York
3. Can Be Dictionary Keys
Lists cannot be dictionary keys, but tuples can:
# This works
locations = {
(40.7128, -74.0060): "New York",
(51.5074, -0.1278): "London"
}
print(locations[(40.7128, -74.0060)]) # New York
# This fails
# locations = {[40.7128, -74.0060]: "New York"} # TypeError!
4. Return Multiple Values
Functions can return tuples:
def get_stats(numbers):
return min(numbers), max(numbers), sum(numbers)
low, high, total = get_stats([1, 2, 3, 4, 5])
print(low, high, total) # 1 5 15
Tuple Unpacking
# Basic unpacking
t = (1, 2, 3)
a, b, c = t
print(a, b, c) # 1 2 3
# Swap values (elegant!)
x, y = 10, 20
x, y = y, x
print(x, y) # 20 10
# Unpacking with *
t = (1, 2, 3, 4, 5)
first, *middle, last = t
print(first) # 1
print(middle) # [2, 3, 4]
print(last) # 5
Looping Through Tuples
t = ('a', 'b', 'c')
# Basic loop
for item in t:
print(item)
# With index
for i, item in enumerate(t):
print(f"{i}: {item}")
# Loop through list of tuples
points = [(0, 0), (1, 2), (3, 4)]
for x, y in points:
print(f"x={x}, y={y}")
Tuple Methods
Tuples have only two methods (because they're immutable):
t = (1, 2, 3, 2, 2, 4)
# Count occurrences
print(t.count(2)) # 3
# Find index
print(t.index(3)) # 2
Tuples vs Lists Summary
| Feature | Tuple | List |
|---|---|---|
| Syntax | (1, 2, 3) | [1, 2, 3] |
| Mutable | No | Yes |
| Speed | Faster | Slower |
| Memory | Less | More |
| Dictionary key | Yes | No |
| Use case | Fixed data | Changing data |
Tuple Exercises
Exercise 1: Create a tuple with your name, age, and city. Print each element.
Exercise 2: Given t = (1, 2, 3, 4, 5), print the first and last elements.
Exercise 3: Write a function that returns the min, max, and average of a list as a tuple.
Exercise 4: Swap two variables using tuple unpacking.
Exercise 5: Create a tuple from the string "ATGC" and count how many times 'A' appears.
Exercise 6: Given a list of (x, y) coordinates, calculate the distance of each from origin.
Exercise 7: Use a tuple as a dictionary key to store city names by their (latitude, longitude).
Exercise 8: Unpack (1, 2, 3, 4, 5) into first, middle (as list), and last.
Exercise 9: Create a function that returns the quotient and remainder of two numbers as a tuple.
Exercise 10: Loop through [(1, 'a'), (2, 'b'), (3, 'c')] and print each pair.
Exercise 11: Convert a list [1, 2, 3] to a tuple and back to a list.
Exercise 12: Find the index of 'G' in the tuple ('A', 'T', 'G', 'C').
Exercise 13: Create a tuple of tuples representing a 3x3 grid and print the center element.
Exercise 14: Given two tuples, concatenate them into a new tuple.
Exercise 15: Sort a list of (name, score) tuples by score in descending order.
Solutions
# Exercise 1
person = ("Mahmoud", 25, "Bologna")
print(person[0], person[1], person[2])
# Exercise 2
t = (1, 2, 3, 4, 5)
print(t[0], t[-1])
# Exercise 3
def stats(numbers):
return min(numbers), max(numbers), sum(numbers)/len(numbers)
print(stats([1, 2, 3, 4, 5]))
# Exercise 4
x, y = 10, 20
x, y = y, x
print(x, y)
# Exercise 5
dna = tuple("ATGC")
print(dna.count('A'))
# Exercise 6
import math
coords = [(3, 4), (0, 5), (1, 1)]
for x, y in coords:
dist = math.sqrt(x**2 + y**2)
print(f"({x}, {y}): {dist:.2f}")
# Exercise 7
cities = {
(40.71, -74.00): "New York",
(51.51, -0.13): "London"
}
print(cities[(40.71, -74.00)])
# Exercise 8
t = (1, 2, 3, 4, 5)
first, *middle, last = t
print(first, middle, last)
# Exercise 9
def div_mod(a, b):
return a // b, a % b
print(div_mod(17, 5)) # (3, 2)
# Exercise 10
pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
for num, letter in pairs:
print(f"{num}: {letter}")
# Exercise 11
L = [1, 2, 3]
t = tuple(L)
L2 = list(t)
print(t, L2)
# Exercise 12
dna = ('A', 'T', 'G', 'C')
print(dna.index('G')) # 2
# Exercise 13
grid = ((1, 2, 3), (4, 5, 6), (7, 8, 9))
print(grid[1][1]) # 5
# Exercise 14
t1 = (1, 2)
t2 = (3, 4)
t3 = t1 + t2
print(t3) # (1, 2, 3, 4)
# Exercise 15
scores = [("Alice", 85), ("Bob", 92), ("Charlie", 78)]
sorted_scores = sorted(scores, key=lambda x: x[1], reverse=True)
print(sorted_scores)
Part 2: Sets
What is a Set?
A set is a collection of unique elements with no duplicates. Sets work like mathematical sets.
# Duplicates are automatically removed
S = {1, 2, 2, 3, 3, 3}
print(S) # {1, 2, 3}
# Unordered - no indexing
# print(S[0]) # TypeError!
Creating Sets
# With curly braces
S = {1, 2, 3, 4, 5}
# From a list (removes duplicates)
S = set([1, 2, 2, 3, 3])
print(S) # {1, 2, 3}
# From a string
S = set("hello")
print(S) # {'h', 'e', 'l', 'o'} (no duplicate 'l')
# Empty set (NOT {} - that's an empty dict!)
S = set()
print(type(S)) # <class 'set'>
print(type({})) # <class 'dict'>
Adding and Removing Elements
S = {1, 2, 3}
# Add single element
S.add(4)
print(S) # {1, 2, 3, 4}
# Add multiple elements
S.update([5, 6, 7])
print(S) # {1, 2, 3, 4, 5, 6, 7}
# Remove element (raises error if not found)
S.remove(7)
print(S) # {1, 2, 3, 4, 5, 6}
# Discard element (no error if not found)
S.discard(100) # No error
S.discard(6)
print(S) # {1, 2, 3, 4, 5}
# Pop random element
x = S.pop()
print(x) # Some element (unpredictable which one)
# Clear all elements
S.clear()
print(S) # set()
Membership Testing
Very fast - O(1):
S = {1, 2, 3, 4, 5}
print(3 in S) # True
print(100 in S) # False
print(100 not in S) # True
Looping Through Sets
S = {'a', 'b', 'c'}
# Basic loop
for item in S:
print(item)
# With enumerate
for i, item in enumerate(S):
print(f"{i}: {item}")
Note: Sets are unordered - iteration order is not guaranteed!
Set Operations (The Powerful Part!)
Sets support mathematical set operations.
Union: Elements in Either Set
A = {1, 2, 3}
B = {3, 4, 5}
# Using | operator
print(A | B) # {1, 2, 3, 4, 5}
# Using method
print(A.union(B)) # {1, 2, 3, 4, 5}
Intersection: Elements in Both Sets
A = {1, 2, 3}
B = {3, 4, 5}
# Using & operator
print(A & B) # {3}
# Using method
print(A.intersection(B)) # {3}
Difference: Elements in A but Not in B
A = {1, 2, 3}
B = {3, 4, 5}
# Using - operator
print(A - B) # {1, 2}
print(B - A) # {4, 5}
# Using method
print(A.difference(B)) # {1, 2}
Symmetric Difference: Elements in Either but Not Both
A = {1, 2, 3}
B = {3, 4, 5}
# Using ^ operator
print(A ^ B) # {1, 2, 4, 5}
# Using method
print(A.symmetric_difference(B)) # {1, 2, 4, 5}
Subset and Superset
A = {1, 2}
B = {1, 2, 3, 4}
# Is A a subset of B?
print(A <= B) # True
print(A.issubset(B)) # True
# Is B a superset of A?
print(B >= A) # True
print(B.issuperset(A)) # True
# Proper subset (subset but not equal)
print(A < B) # True
print(A < A) # False
Disjoint: No Common Elements
A = {1, 2}
B = {3, 4}
C = {2, 3}
print(A.isdisjoint(B)) # True (no overlap)
print(A.isdisjoint(C)) # False (2 is common)
Set Operations Summary
| Operation | Operator | Method | Result |
|---|---|---|---|
| Union | A \| B | A.union(B) | All elements from both |
| Intersection | A & B | A.intersection(B) | Common elements |
| Difference | A - B | A.difference(B) | In A but not in B |
| Symmetric Diff | A ^ B | A.symmetric_difference(B) | In either but not both |
| Subset | A <= B | A.issubset(B) | True if A ⊆ B |
| Superset | A >= B | A.issuperset(B) | True if A ⊇ B |
| Disjoint | - | A.isdisjoint(B) | True if no overlap |
In-Place Operations
Modify the set directly (note the method names end in _update):
A = {1, 2, 3}
B = {3, 4, 5}
# Union in-place
A |= B # or A.update(B)
print(A) # {1, 2, 3, 4, 5}
# Intersection in-place
A = {1, 2, 3}
A &= B # or A.intersection_update(B)
print(A) # {3}
# Difference in-place
A = {1, 2, 3}
A -= B # or A.difference_update(B)
print(A) # {1, 2}
Practical Examples
Remove Duplicates from List
L = [1, 2, 2, 3, 3, 3, 4]
unique = list(set(L))
print(unique) # [1, 2, 3, 4]
Find Common Elements
list1 = [1, 2, 3, 4]
list2 = [3, 4, 5, 6]
common = set(list1) & set(list2)
print(common) # {3, 4}
Find Unique DNA Bases
dna = "ATGCATGCATGC"
bases = set(dna)
print(bases) # {'A', 'T', 'G', 'C'}
Set Exercises
Exercise 1: Create a set from the list [1, 2, 2, 3, 3, 3] and print it.
Exercise 2: Add the number 10 to a set {1, 2, 3}.
Exercise 3: Remove duplicates from [1, 1, 2, 2, 3, 3, 4, 4].
Exercise 4: Find common elements between {1, 2, 3, 4} and {3, 4, 5, 6}.
Exercise 5: Find elements in {1, 2, 3} but not in {2, 3, 4}.
Exercise 6: Find all unique characters in the string "mississippi".
Exercise 7: Check if {1, 2} is a subset of {1, 2, 3, 4}.
Exercise 8: Find symmetric difference of {1, 2, 3} and {3, 4, 5}.
Exercise 9: Check if two sets {1, 2} and {3, 4} have no common elements.
Exercise 10: Given DNA sequence "ATGCATGC", create set of unique nucleotides.
Exercise 11: Combine sets {1, 2}, {3, 4}, {5, 6} into one set.
Exercise 12: Given two lists of students, find students in both classes.
Exercise 13: Remove element 3 from set {1, 2, 3, 4} safely (no error if missing).
Exercise 14: Create a set of prime numbers less than 20 and check membership of 17.
Exercise 15: Given three sets A, B, C, find elements that are in all three.
Solutions
# Exercise 1
S = set([1, 2, 2, 3, 3, 3])
print(S) # {1, 2, 3}
# Exercise 2
S = {1, 2, 3}
S.add(10)
print(S)
# Exercise 3
L = [1, 1, 2, 2, 3, 3, 4, 4]
print(list(set(L)))
# Exercise 4
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
print(A & B) # {3, 4}
# Exercise 5
A = {1, 2, 3}
B = {2, 3, 4}
print(A - B) # {1}
# Exercise 6
print(set("mississippi"))
# Exercise 7
A = {1, 2}
B = {1, 2, 3, 4}
print(A <= B) # True
# Exercise 8
A = {1, 2, 3}
B = {3, 4, 5}
print(A ^ B) # {1, 2, 4, 5}
# Exercise 9
A = {1, 2}
B = {3, 4}
print(A.isdisjoint(B)) # True
# Exercise 10
dna = "ATGCATGC"
print(set(dna)) # {'A', 'T', 'G', 'C'}
# Exercise 11
A = {1, 2}
B = {3, 4}
C = {5, 6}
print(A | B | C) # {1, 2, 3, 4, 5, 6}
# Exercise 12
class1 = ["Alice", "Bob", "Charlie"]
class2 = ["Bob", "Diana", "Charlie"]
print(set(class1) & set(class2)) # {'Bob', 'Charlie'}
# Exercise 13
S = {1, 2, 3, 4}
S.discard(3) # Safe removal
S.discard(100) # No error
print(S)
# Exercise 14
primes = {2, 3, 5, 7, 11, 13, 17, 19}
print(17 in primes) # True
# Exercise 15
A = {1, 2, 3, 4}
B = {2, 3, 4, 5}
C = {3, 4, 5, 6}
print(A & B & C) # {3, 4}
Summary: When to Use What?
| Data Type | Use When |
|---|---|
| List | Ordered, allow duplicates, need to modify |
| Tuple | Ordered, no modification needed, dictionary keys |
| Set | No duplicates, fast membership testing, set operations |
| Dict | Key-value mapping, fast lookup by key |