Chapter 5 — Core Data Structures: Lists, Tuples, Sets, Dictionaries
Data lives in structures. This chapter covers Python's four core containers and shows how to choose the right one — the conceptual bridge to the tabular data structures used throughout the rest of the book.
Learning Objectives
- Create and manipulate lists, including comprehensions.
- Copy lists correctly (shallow vs deep).
- Use tuples and understand immutability.
- Perform set operations and reason about performance.
- Build and iterate dictionaries, including comprehensions.
- Choose the appropriate data structure for a task.
- Nest containers to model records.
Prerequisites / Imports
Uses the standard copy and time modules.
import copy
import time
1 Lists
Lists are ordered, mutable sequences. Comprehensions build lists concisely.
nums = [3, 1, 4, 1, 5, 9, 2, 6]
nums.append(5)
nums.sort()
print(nums)
print('squares:', [x**2 for x in range(6)])
print('evens:', [x for x in nums if x % 2 == 0])
[1, 1, 2, 3, 4, 5, 5, 6, 9] squares: [0, 1, 4, 9, 16, 25] evens: [2, 4, 6]
2 Copying Lists
list.copy() and list() make shallow copies; copy.deepcopy duplicates nested objects.
original = [[1, 2], [3, 4]]
shallow = original.copy()
shallow[0].append(99)
print('original after shallow mutation:', original)
deep = copy.deepcopy(original)
deep[0].append(77)
print('original after deep mutation:', original)
original after shallow mutation: [[1, 2, 99], [3, 4]] original after deep mutation: [[1, 2, 99], [3, 4]]
3 Searching and Sorting
in tests membership; sorted() returns a new list; .sort() sorts in place.
data = [5, 2, 8, 1, 9, 3]
print('contains 8:', 8 in data)
print('sorted new:', sorted(data, reverse=True))
data.sort()
print('in-place:', data)
contains 8: True sorted new: [9, 8, 5, 3, 2, 1] in-place: [1, 2, 3, 5, 8, 9]
4 Tuples
Tuples are immutable and often used for fixed records and multiple return values.
point = (3, 4)
x, y = point # unpacking
print('distance from origin:', (x**2 + y**2) ** 0.5)
pairs = {(1,'a'), (2,'b')} # tuples can be set/dict keys
print(pairs)
distance from origin: 5.0
{(2, 'b'), (1, 'a')}
5 Sets
Sets store unique items and support mathematical set operations. Membership is O(1).
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print('union:', a | b)
print('intersection:', a & b)
print('difference:', a - b)
print('symmetric diff:', a ^ b)
union: {1, 2, 3, 4, 5, 6}
intersection: {3, 4}
difference: {1, 2}
symmetric diff: {1, 2, 5, 6}
# Performance: membership in a list vs a set
big_list = list(range(100_000))
big_set = set(big_list)
t0 = time.perf_counter()
_ = 99_999 in big_list
t_list = time.perf_counter() - t0
t0 = time.perf_counter()
_ = 99_999 in big_set
t_set = time.perf_counter() - t0
print(f'list lookup: {t_list*1e6:.1f} us')
print(f'set lookup: {t_set*1e6:.1f} us')
list lookup: 6936.0 us set lookup: 4.4 us
6 Dictionaries
Dictionaries map keys to values. Use .get() for safe access and comprehensions to build them.
prices = {'apple': 1.2, 'banana': 0.5, 'cherry': 3.0}
print(prices.get('banana'), prices.get('date', 'N/A'))
print('uppercased keys:', {k.upper(): v for k, v in prices.items()})
0.5 N/A
uppercased keys: {'APPLE': 1.2, 'BANANA': 0.5, 'CHERRY': 3.0}
7 Choosing the Right Structure
| Structure | Ordered | Mutable | Use when |
|---|---|---|---|
| list | yes | yes | sequence of items |
| tuple | yes | no | fixed record / hashable key |
| set | no | yes | unique items, fast membership |
| dict | yes* | yes | key→value mapping |
(*dicts preserve insertion order since Python 3.7.)
8 Nesting: The Bridge to Tabular Data
A list of dictionaries models rows of a table — exactly what pandas will formalize.
people = [
{'name': 'Ada', 'age': 36, 'role': 'engineer'},
{'name': 'Bo', 'age': 28, 'role': 'analyst'},
{'name': 'Cy', 'age': 44, 'role': 'manager'},
]
ages = [p['age'] for p in people]
print('ages:', ages)
print('average age:', sum(ages) / len(ages))
ages: [36, 28, 44] average age: 36.0
Case Study: Inventory Management
Model a store inventory as a list of product dicts with add/sell/search/value operations.
inventory = [
{'name': 'Widget', 'price': 4.50, 'stock': 10},
{'name': 'Gadget', 'price': 12.75, 'stock': 5},
{'name': 'Cable', 'price': 1.20, 'stock': 50},
]
def find(name):
for p in inventory:
if p['name'] == name:
return p
return None
def sell(name, qty):
p = find(name)
if p and p['stock'] >= qty:
p['stock'] -= qty
return p['price'] * qty
return None
def total_value():
return sum(p['price'] * p['stock'] for p in inventory)
print('Sold 3 Widgets: $', sell('Widget', 3))
print('Sold 2 Gadgets: $', sell('Gadget', 2))
print('Try selling 100 Cables:', sell('Cable', 100))
print('Total inventory value: $', round(total_value(), 2))
for p in inventory:
print(f" {p['name']:<8} stock={p['stock']}")
Sold 3 Widgets: $ 13.5 Sold 2 Gadgets: $ 25.5 Try selling 100 Cables: None Total inventory value: $ 129.75 Widget stock=7 Gadget stock=3 Cable stock=50
Exercises
- Use a comprehension to create the squares of 1–10.
- Deep-copy a nested list and show the original is unaffected by mutation.
- Given two lists, find elements common to both using sets.
- Build a dictionary mapping each word in a sentence to its length.
- Count word frequencies in a paragraph using a dict.
- Remove duplicates from a list using a set, preserving order.
- Time membership lookups in a list of 100,000 items vs a set.
- Model a phone book as a dict and look up three names.
- Convert a list of dicts into a dict of lists (columnar form).
- Explain when you would choose a tuple over a list.
Python Data Science: From Foundations to Applications — Chapter 5