Chapter 6

Collections

6.1 Lists · 6.2 Tuples · 6.3 Sets

← → or Space to navigate · F for fullscreen

6.1 Lists

Ordered, mutable sequences — Python's most versatile collection

Creating Lists

Literal

fruits = ["apple", "banana", "cherry"]
mixed  = [1, "hello", 3.14, True]
empty  = []

list() constructor

list("abc")        # ['a', 'b', 'c']
list(range(5))     # [0, 1, 2, 3, 4]
list((1, 2, 3))    # from tuple

List comprehension

squares = [x**2 for x in range(6)]
# [0, 1, 4, 9, 16, 25]

evens = [x for x in range(10) if x % 2 == 0]

Nested lists

matrix = [[1, 2], [3, 4], [5, 6]]
matrix[1][0]   # 3

Strings ↔ Lists

words = "hello world".split()
# ['hello', 'world']

" ".join(words)   # 'hello world'

Lists are mutable — elements can be added, removed, or changed after creation. Order is preserved and duplicates are allowed.

Accessing & Slicing

Indexing (zero-based)

fruits = ["apple", "banana", "cherry"]

fruits[0]    # 'apple'
fruits[-1]   # 'cherry'   (last element)
fruits[10]   # IndexError

Slicing [start:stop:step]

fruits[1:]    # ['banana', 'cherry']
fruits[:2]    # ['apple', 'banana']
fruits[::2]   # every other element
fruits[::-1]  # reversed

Query methods

nums = [3, 1, 4, 1, 5, 9, 2, 6]

len(nums)         # 8
nums.count(1)     # 2
nums.index(5)     # 4  (first occurrence)
5 in nums         # True

Unpacking

a, b, c = [10, 20, 30]
first, *rest = [1, 2, 3, 4]
# first=1, rest=[2, 3, 4]

Modifying Lists

Add elements

fruits.append("date")          # end
fruits.insert(1, "avocado")    # at index
fruits.extend(["elderberry"])  # merge list

Remove elements

fruits.remove("banana")   # by value
fruits.pop()              # last (returns it)
fruits.pop(0)             # by index
del fruits[1]             # by index, no return
fruits.clear()            # empty the list

Sort & reverse

nums = [3, 1, 4, 1, 5]
nums.sort()              # in-place
nums.sort(reverse=True)
nums.reverse()           # in-place

sorted(nums)             # returns new list

Useful helpers

min(nums), max(nums), sum(nums)
enumerate(nums)   # (index, value) pairs
zip(a, b)         # pair two lists

Aliasing vs. Copying

Aliasing — shared reference

a = [1, 2, 3]
b = a          # b points to same list
b.append(4)
print(a)       # [1, 2, 3, 4]  ← changed!

Shallow copy — independent top level

b = a[:]       # slice copy
b = a.copy()   # .copy() method
b = list(a)    # list() constructor

b.append(4)
print(a)       # [1, 2, 3]  ← safe

Deep copy — independent at every level

import copy

nested = [[1, 2], [3, 4]]
deep = copy.deepcopy(nested)

deep[0].append(99)
print(nested)  # [[1, 2], [3, 4]]  ← safe

Shallow copy is safe for flat lists. Use deepcopy when the list contains other mutable objects (nested lists, dicts).

6.2 Tuples

Ordered, immutable sequences — safe, hashable, fast

Creating & Using Tuples

Literal (comma makes the tuple)

point   = (3, 4)
single  = (42,)     # trailing comma required
empty   = ()
no_paren = 1, 2, 3  # parens optional

tuple() constructor

tuple([1, 2, 3])    # from list
tuple("abc")        # ('a', 'b', 'c')
tuple(range(4))     # (0, 1, 2, 3)

Accessing (same as lists)

point[0]     # 3
point[-1]    # 4
point[0:1]   # (3,)

Immutability

point[0] = 99   # TypeError — can't modify

Use a tuple when data should not change — coordinates, RGB colors, database rows, function return values. Tuples are hashable (can be dict keys or set elements); lists are not.

Choosing list vs. tuple

list tuple
Mutable
Hashable
Performance good slightly faster

Tuple Unpacking & Functions

Basic unpacking

x, y = (3, 4)
a, b, c = "abc"       # works on any iterable

# starred unpacking
first, *rest = (1, 2, 3, 4)
# first=1, rest=[2, 3, 4]

zip() and enumerate()

names  = ["alice", "bob"]
scores = [92, 85]

for name, score in zip(names, scores):
    print(name, score)

for i, name in enumerate(names):
    print(i, name)

Multiple return values

def min_max(nums):
    return min(nums), max(nums)  # returns tuple

lo, hi = min_max([3, 1, 4, 1, 5])

Argument packing with *args

def total(*args):    # args is a tuple
    return sum(args)

total(1, 2, 3, 4)   # 10

Sorting by tuple key

pairs = [("bob", 85), ("alice", 92)]
pairs.sort(key=lambda p: p[1])
# sort by score (second element)

6.3 Sets

Unordered collections of unique, hashable elements

Creating & Accessing Sets

Create

a = {1, 2, 3}
b = set([3, 4, 5])    # from list
empty = set()          # NOT {} (that's a dict)

# duplicates removed automatically
s = {1, 2, 2, 3, 3}   # {1, 2, 3}

No indexing — iterate or test membership

3 in a      # True   O(1)
6 not in a  # True

for item in a:
    print(item)    # order not guaranteed

When to use a set

Need Use
Ordered, duplicates OK list
Fixed structure, hashable tuple
Unique elements, fast lookup set
Key-value mapping dict

Sets are great for deduplication and membership testing. x in set is O(1); x in list is O(n).

Set Operations

a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
Operation Operator Method
Union a | b a.union(b)
Intersection a & b a.intersection(b)
Difference a - b a.difference(b)
Sym. difference a ^ b a.symmetric_difference(b)
a | b   # {1, 2, 3, 4, 5, 6}
a & b   # {3, 4}
a - b   # {1, 2}
a ^ b   # {1, 2, 5, 6}

Modify in place

a.add(5)          # add one element
a.update({6, 7})  # add multiple

a.remove(1)       # KeyError if missing
a.discard(99)     # safe — no error
a.pop()           # remove arbitrary element

Subset / superset

{1, 2} <= {1, 2, 3}   # True  (subset)
{1, 2, 3} >= {1, 2}   # True  (superset)

Frozensets & Set Comprehensions

frozenset — immutable set

fs = frozenset({1, 2, 3})
# fs.add(4)   ← AttributeError

# Can be a dict key or set element
graph = {frozenset({1, 2}): "edge A"}
set frozenset
Mutable
Hashable
Dict key

Set comprehension

# unique squares of even numbers
s = {x**2 for x in range(10) if x % 2 == 0}
# {0, 4, 16, 36, 64}

# deduplicate a list
words = ["the", "cat", "the", "mat"]
unique = {w.lower() for w in words}

O(1) membership — why it matters

# set membership is O(1) vs O(n) for list
big = set(range(1_000_000))
999_999 in big   # instant

Chapter 6 — Quick Reference

Type Ordered Mutable Duplicates Hashable Literal
list [1, 2]
tuple (1, 2)
set {1, 2}
frozenset frozenset({1,2})
Task Idiom
Deduplicate list(set(lst))
Unpack a, b, *rest = lst
Copy flat list lst[:] or lst.copy()
Multiple return return a, b → unpack with x, y = f()
Set ops | & - ^
Membership x in s — O(1) for set/dict, O(n) for list

End of Chapter 6

Next: Chapter 7 — Dictionaries

key-value mappings · core operations · dictionary patterns