0% found this document useful (0 votes)
3 views22 pages

Topic 4 Python Data Structures

The document provides an overview of Python data structures, including lists, tuples, dictionaries, sets, and strings. It covers their characteristics, such as mutability and memory usage, along with practical examples and methods for creating, accessing, and modifying these structures. Additionally, it includes a section on comprehensions and a guide for choosing the appropriate data structure for various use cases.

Uploaded by

triffinmunene
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views22 pages

Topic 4 Python Data Structures

The document provides an overview of Python data structures, including lists, tuples, dictionaries, sets, and strings. It covers their characteristics, such as mutability and memory usage, along with practical examples and methods for creating, accessing, and modifying these structures. Additionally, it includes a section on comprehensions and a guide for choosing the appropriate data structure for various use cases.

Uploaded by

triffinmunene
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Introduction to Python | Data Structures Lecture Notes 2025–2026

INTRODUCTION TO PYTHON
Lecture Notes
Python Data Structures
Lists • Tuples • Dictionaries • Sets • Strings as Sequences • Comprehensions • Choosing
the Right Structure

Topic Covered In This Document


1. Introduction to Data Structures Overview, mutability, memory
2. Lists Create, index, slice, modify, methods, comprehensions
3. Tuples Immutability, packing/unpacking, use cases
4. Dictionaries Key-value pairs, CRUD, iteration, comprehensions
5. Sets Unique values, set operations, frozensets
6. Strings as Sequences Indexing, slicing, methods, f-strings
7. Comprehensions List, dict, set comprehensions
8. Choosing a Data Structure Decision guide, comparison table
9. Practice Exercises Graded exercises with solutions

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

1. Introduction to Python Data Structures

What is a Data Structure?


A data structure is a way of organising and storing data in a program so that it can be accessed,
modified, and processed efficiently. In Python, data structures are built into the language — you
do not need to import anything to use the four core types.

1.1 The Four Core Python Data Structures


Structure Syntax Ordered Mutable Duplicates Key Feature
List [1, 2, 3] Yes Yes ✓ Yes General-purpose
ordered collection
Tuple (1, 2, 3) Yes No ✗ Yes Fixed / immutable
sequence
Dictionary {'a': 1} Yes* Yes ✓ Keys: No Key-value lookup
Set {1, 2, 3} No Yes ✓ No Unique values, fast
membership test
* Dictionaries maintain insertion order from Python 3.7 onwards.

1.2 Mutability
Mutability determines whether you can change a data structure after it is created.
• Mutable structures (List, Dict, Set) can be changed in place — you can add, remove, or
modify elements.
• Immutable structures (Tuple, Frozenset, String) cannot be changed once created. Any
'modification' creates a new object.

⚑ Why Mutability Matters


Mutable objects are passed by reference — if you pass a list to a function and modify it
inside, the original list changes. Immutable objects are safe to pass around without fear of
accidental modification. This matters a great deal in data science when sharing datasets
between functions.

1.3 Memory and Performance Overview


Operation List Tuple Dictionary Set
Access by index O(1) O(1) N/A N/A
Access by key N/A N/A O(1) N/A
Membership test O(n) O(n) O(1) O(1)
Append/Add O(1) N/A O(1) O(1)
Insert at i O(n) N/A N/A N/A
Delete O(n) N/A O(1) O(1)
O(1) = constant time (fast). O(n) = linear time (slows as size grows).

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

2. Lists

A list is an ordered, mutable sequence of elements. It is the most versatile and commonly used
data structure in Python. Lists can hold elements of any type — even mixed types — and can
grow or shrink dynamically.

2.1 Creating Lists


# Empty list
empty = []

# Homogeneous lists
scores = [85, 92, 78, 95, 88]
names = ['Alice', 'Bob', 'Carol', 'Dave']
prices = [19.99, 34.50, 5.99]

# Mixed-type list (Python allows this)


record = ['Alice', 30, True, 95.5, None]

# Nested list (2-D matrix)


matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]

# Create from other sequences


from_range = list(range(5)) # [0, 1, 2, 3, 4]
from_tuple = list((1, 2, 3)) # [1, 2, 3]
from_string = list('hello') # ['h','e','l','l','o']

2.2 Indexing and Slicing


Python uses zero-based indexing. Negative indices count from the end.
fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry']

# Positive indexing
print(fruits[0]) # 'apple' — first element
print(fruits[2]) # 'cherry'
print(fruits[-1]) # 'elderberry' — last element
print(fruits[-2]) # 'date' — second from last

# Slicing [start : stop : step] stop is EXCLUSIVE


print(fruits[1:3]) # ['banana', 'cherry']
print(fruits[:2]) # ['apple', 'banana'] — from start
print(fruits[2:]) # ['cherry', 'date', 'elderberry'] — to end
print(fruits[::2]) # ['apple', 'cherry', 'elderberry'] — every 2nd
print(fruits[::-1]) # reversed list

# Nested list access


matrix = [[1,2,3],[4,5,6],[7,8,9]]
print(matrix[1][2]) # 6 (row 1, column 2)

2.3 Modifying Lists — Mutability in Action


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

# Change an element
fruits[0] = 'avocado'
print(fruits) # ['avocado', 'banana', 'cherry']

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

# append() — add ONE element to the end


[Link]('date')

# insert(index, value) — insert at a specific position


[Link](1, 'blueberry') # insert at index 1

# extend() — add all elements from another iterable


[Link](['fig', 'grape'])

# remove() — remove FIRST occurrence of a value


[Link]('banana')

# pop(index) — remove AND return element at index


last = [Link]() # removes last element
third = [Link](2) # removes element at index 2

# del — delete by index or slice


del fruits[0]
del fruits[1:3]

# clear() — remove all elements


[Link]() # fruits is now []

2.4 Searching and Sorting


nums = [5, 2, 8, 1, 9, 3, 2]

# index() — position of first occurrence


print([Link](2)) # 1

# count() — how many times a value appears


print([Link](2)) # 2

# sort() — sort IN PLACE (modifies the list)


[Link]()
print(nums) # [1, 2, 2, 3, 5, 8, 9]
[Link](reverse=True) # descending

# sorted() — returns a NEW sorted list, original unchanged


original = [5, 2, 8, 1]
new_list = sorted(original) # [1, 2, 5, 8]
print(original) # [5, 2, 8, 1] — unchanged

# Sort by custom key using lambda


students = [('Bob', 85), ('Alice', 92), ('Carol', 78)]
[Link](key=lambda s: s[1], reverse=True)
# [('Alice', 92), ('Bob', 85), ('Carol', 78)]

# Aggregates
print(min(nums), max(nums), sum(nums), len(nums))

2.5 List Comprehensions


List comprehensions are a concise, Pythonic way to build new lists. They replace many for-loop
patterns with a single readable line.
Syntax: [ expression for item in iterable if condition ]

# Basic: squares of 0–9

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

squares = [x**2 for x in range(10)]


# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# With condition: only even squares


even_sq = [x**2 for x in range(10) if x % 2 == 0]
# [0, 4, 16, 36, 64]

# Transform strings
names = ['alice', 'bob', 'carol']
upper = [[Link]() for name in names]
# ['ALICE', 'BOB', 'CAROL']

# Filter: scores above 50


scores = [85, 42, 91, 67, 38, 95]
passing = [s for s in scores if s >= 50]
# [85, 91, 67, 95]

# Ternary inside comprehension


grades = ['Pass' if s >= 50 else 'Fail' for s in scores]
# ['Pass', 'Fail', 'Pass', 'Pass', 'Fail', 'Pass']

# Flatten a 2-D matrix into 1-D


matrix = [[1,2,3],[4,5,6],[7,8,9]]
flat = [val for row in matrix for val in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

2.6 Common List Methods — Quick Reference


Method Description Returns Example
append(x) Add x to end None [Link](5)
insert(i, x) Insert x at index i None [Link](0, 'a')
extend(iter) Add all items from iterable None [Link]([1,2])
remove(x) Remove first occurrence None [Link](3)
of x
pop(i) Remove & return item at item [Link]()
index i
index(x) Index of first occurrence of int [Link](7)
x
count(x) Count occurrences of x int [Link](2)
sort() Sort in place None [Link]()
reverse() Reverse in place None [Link]()
copy() Shallow copy list lst2 = [Link]()
clear() Remove all items None [Link]()

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

3. Tuples

A tuple is an ordered, immutable sequence. Once created, its elements cannot be added,
removed, or changed. Tuples are faster and use less memory than lists, and can be used as
dictionary keys.

3.1 Creating Tuples


# Empty tuple
t0 = ()

# Single-element tuple — the COMMA is essential


t1 = (42,) # This IS a tuple
t2 = (42) # This is just the integer 42 — NOT a tuple!

# Multi-element tuples
coords = (10.5, 20.3) # latitude, longitude
person = ('Alice', 30, 'F') # name, age, gender
rgb = (255, 128, 0) # red, green, blue

# Tuple packing — parentheses are optional


point = 3, 4 # same as (3, 4)

# Convert from other sequences


from_list = tuple([1, 2, 3]) # (1, 2, 3)
from_str = tuple('abc') # ('a', 'b', 'c')

3.2 Indexing and Slicing


Tuples use the same zero-based indexing and slicing syntax as lists.
t = (10, 20, 30, 40, 50)

print(t[0]) # 10 — first element


print(t[-1]) # 50 — last element
print(t[1:4]) # (20, 30, 40)
print(t[::-1]) # (50, 40, 30, 20, 10) — reversed

# Nested tuple access


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

3.3 Tuple Unpacking


Tuple unpacking assigns elements to individual variables in one line — one of Python's most
elegant features.
# Basic unpacking
coords = (48.8, 2.35) # Paris: lat, lon
lat, lon = coords
print(lat) # 48.8
print(lon) # 2.35

# Swap two variables without a temporary variable


a, b = 10, 20
a, b = b, a
print(a, b) # 20 10

# Extended unpacking with *

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

first, *rest = (1, 2, 3, 4, 5)


print(first) # 1
print(rest) # [2, 3, 4, 5]

*start, last = (1, 2, 3, 4, 5)


print(last) # 5

# Unpacking in a for loop — very common pattern


students = [('Alice', 90), ('Bob', 85), ('Carol', 92)]
for name, score in students:
print(f'{name}: {score}')
# Alice: 90 Bob: 85 Carol: 92

3.4 When to Use Tuples vs Lists


Criterion Tuple List
Mutability Immutable — cannot change Mutable — can change
Syntax Parentheses () or commas Square brackets []
Performance Slightly faster, less memory Slightly slower, more memory
As dict key Yes — tuples are hashable No — lists are not hashable
Typical use Fixed records, coordinates, RGB Collections that grow/shrink
Intent signal Data will NOT change Data may change

⚑ Lecturer Tip — Tuples Signal Intent


When you use a tuple, you are communicating to other programmers: 'this data is fixed and
should not change.' Use tuples for things like GPS coordinates, database row records, RGB
colour values, and function return values where order is significant.

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

4. Dictionaries

A dictionary (dict) stores data as key-value pairs. Each key maps to exactly one value. Keys
must be unique and immutable. Dictionaries are the closest Python equivalent to a JSON object, a
database record, or a hash map.

4.1 Creating Dictionaries


# Empty dict
d = {} # or: d = dict()

# Dictionary literal
student = {'name': 'Alice', 'age': 22, 'gpa': 3.8}

# Mixed value types


record = {
'id': 12345,
'name': 'Alice Doe',
'scores': [85, 92, 78], # list as a value
'active': True,
'email': None
}

# From keyword arguments


d2 = dict(name='Bob', age=25, city='Nairobi')

# From a list of (key, value) pairs


pairs = [('a', 1), ('b', 2), ('c', 3)]
d3 = dict(pairs) # {'a': 1, 'b': 2, 'c': 3}

4.2 Accessing and Modifying Values


student = {'name': 'Alice', 'age': 22, 'gpa': 3.8}

# READ — access by key


print(student['name']) # 'Alice'
# student['email'] → KeyError if key doesn't exist

# Safe access with get() — returns None or a default


print([Link]('email')) # None
print([Link]('email', 'N/A')) # 'N/A'

# CREATE / UPDATE
student['email'] = 'alice@[Link]' # add new key
student['age'] = 23 # update existing key

# Update multiple keys at once


[Link]({'age': 24, 'gpa': 3.9})

# DELETE
del student['email']
gpa = [Link]('gpa') # removes and returns the value

# Check key existence


print('name' in student) # True
print('gpa' in student) # False (we just removed it)

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

4.3 Iterating over Dictionaries


grades = {'Alice': 90, 'Bob': 85, 'Carol': 92, 'Dave': 78}

# Iterate over KEYS (default)


for name in grades: # same as [Link]()
print(name)

# Iterate over VALUES


for score in [Link]():
print(score)
average = sum([Link]()) / len(grades) # 86.25

# Iterate over KEY-VALUE PAIRS — most common


for name, score in [Link]():
print(f'{name}: {score}')

# setdefault() — set only if key is absent


[Link]('Eve', 0) # adds Eve:0 only if missing

# Merge two dicts (Python 3.9+)


extra = {'Frank': 88}
merged = grades | extra

4.4 Nested Dictionaries


Dictionaries can contain other dictionaries, creating hierarchical data — the same structure as
JSON (the standard format for REST API responses).
students = {
'STU001': {
'name': 'Alice Doe',
'grades': {'Python': 88, 'ML': 92},
'active': True
},
'STU002': {
'name': 'Bob Smith',
'grades': {'Python': 75, 'Stats': 83},
'active': False
}
}

# Access nested values


print(students['STU001']['name']) # 'Alice Doe'
print(students['STU001']['grades']['ML']) # 92

# Safe nested access using chained .get()


ml = [Link]('STU001', {}).get('grades', {}).get('ML', 'N/A')

# Iterate over all students


for sid, info in [Link]():
print(f"{sid}: {info['name']} — Active: {info['active']}")

4.5 Dictionary Comprehensions


Syntax: { key_expr : value_expr for item in iterable if condition }

# Map each number to its square


squares = {x: x**2 for x in range(6)}
# {0:0, 1:1, 2:4, 3:9, 4:16, 5:25}

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

# Invert a dictionary (swap keys and values)


original = {'a': 1, 'b': 2, 'c': 3}
inverted = {v: k for k, v in [Link]()}
# {1: 'a', 2: 'b', 3: 'c'}

# Filter: keep only passing students


grades = {'Alice': 90, 'Bob': 45, 'Carol': 82, 'Dave': 35}
passing = {name: s for name, s in [Link]() if s >= 50}
# {'Alice': 90, 'Carol': 82}

# Normalise scores to 0–1 scale


top = max([Link]()) # 90
norm = {n: round(s/top, 3) for n, s in [Link]()}
# {'Alice': 1.0, 'Bob': 0.5, 'Carol': 0.911, 'Dave': 0.389}

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

5. Sets

A set is an unordered collection of unique elements. Sets are mutable (you can add/remove
items) but do not support indexing, since they have no order. Sets are ideal for removing
duplicates and performing mathematical set operations.

5.1 Creating Sets


# Set literal
fruits = {'apple', 'banana', 'cherry'}

# IMPORTANT: {} creates an empty DICT, not a set!


empty_dict = {} # This is a dict
empty_set = set() # This is a set

# From a list — duplicates are removed automatically


nums = set([1, 2, 2, 3, 3, 3, 4])
print(nums) # {1, 2, 3, 4} — no duplicates

# Common use: remove duplicates from a list


tags = ['python', 'data', 'python', 'ml', 'data', 'python']
unique_tags = list(set(tags))
print(unique_tags) # ['data', 'ml', 'python'] (order may vary)

5.2 Adding and Removing Elements


s = {1, 2, 3}

# add() — add a single element


[Link](4)
print(s) # {1, 2, 3, 4}

# Adding a duplicate does nothing


[Link](2) # {1, 2, 3, 4} — unchanged

# update() — add multiple elements


[Link]([5, 6, 7])

# remove() — raises KeyError if not found


[Link](3)

# discard() — does NOT raise error if not found (safer)


[Link](99) # no error

# pop() — remove and return an ARBITRARY element


x = [Link]()

# clear() — empty the set


[Link]()

5.3 Set Operations


Sets support the four fundamental mathematical operations.
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}

# Union — all elements from both sets

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

print(A | B) # {1, 2, 3, 4, 5, 6, 7, 8}
print([Link](B)) # same result

# Intersection — elements in BOTH sets


print(A & B) # {4, 5}
print([Link](B))

# Difference — in A but NOT in B


print(A - B) # {1, 2, 3}
print([Link](B))

# Symmetric difference — in one but NOT both


print(A ^ B) # {1, 2, 3, 6, 7, 8}
print(A.symmetric_difference(B))

# Subset and superset


C = {1, 2}
print([Link](A)) # True — all of C is in A
print([Link](C)) # True — A contains all of C

# Membership test — O(1) — much faster than lists for large data
print(3 in A) # True
print(9 in A) # False

5.4 Frozenset — Immutable Sets


A frozenset is an immutable version of a set. Because it is hashable, it can be used as a
dictionary key or stored inside another set.
fs = frozenset([1, 2, 3, 4])
# [Link](5) → AttributeError: 'frozenset' has no 'add'

# Use as a dict key


d = {frozenset({1, 2}): 'pair', frozenset({3, 4}): 'other pair'}

⚑ Practical Use of Sets in Data Science


Sets are commonly used to: (1) find unique values in a column quickly, (2) compute overlap
between two lists (e.g., customers who bought both products), (3) fast membership testing
when checking millions of records. Membership testing with a set is O(1); with a list it is O(n)
— a massive difference at scale.

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

6. Strings as Sequences

Strings are immutable sequences of characters. They support the same indexing and slicing
operations as lists and tuples, and have a rich set of built-in methods for text processing — a
crucial skill in data science.

6.1 Indexing and Slicing Strings


s = 'Python'

print(s[0]) # 'P' — first character


print(s[-1]) # 'n' — last character
print(s[0:3]) # 'Pyt' — slice [start:stop]
print(s[2:]) # 'thon'
print(s[::-1]) # 'nohtyP' — reversed

# Strings are immutable — this raises a TypeError:


# s[0] = 'J' → TypeError: 'str' does not support item assignment

6.2 Essential String Methods


text = ' Hello, Data Science! '

# Cleaning
print([Link]()) # remove leading/trailing whitespace
print([Link]()) # remove leading whitespace only
print([Link]()) # remove trailing whitespace only

# Case
print([Link]()) # 'hello, data science!'
print([Link]()) # 'HELLO, DATA SCIENCE!'
print([Link]()) # 'Hello, Data Science!'

# Search
print([Link]('Data')) # 9 (index of first occurrence)
print([Link]('e')) # 2
print([Link](' Hel')) # True
print([Link]('! ')) # True

# Modification
print([Link]('Hello', 'Hi'))
print([Link]().split(', ')) # ['Hello', 'Data Science!']

# Joining
words = ['Python', 'is', 'great']
print(' '.join(words)) # 'Python is great'
print('-'.join(words)) # 'Python-is-great'

# Checking content
print('123'.isdigit()) # True
print('abc'.isalpha()) # True
print('abc123'.isalnum()) # True
print(' '.isspace()) # True

6.3 f-Strings (Formatted String Literals)


f-strings (Python 3.6+) are the preferred way to embed expressions inside strings.
name = 'Alice'

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

score = 95.678
passed = True

# Basic embedding
print(f'Student: {name}')
# Student: Alice

# Format specifiers
print(f'Score: {score:.2f}') # Score: 95.68 (2 decimal places)
print(f'Score: {score:.0f}') # Score: 96 (0 decimal places)
print(f'Score: {score:8.2f}') # Score: 95.68 (width 8, right-aligned)
print(f'Score: {score:<8.2f}') # Score: 95.68 (left-aligned)

# Expressions inside f-strings


print(f'Grade: {"Pass" if passed else "Fail"}')
print(f'Double: {score * 2:.1f}')

# Dictionary values
student = {'name': 'Bob', 'gpa': 3.7}
print(f"Name: {student['name']}, GPA: {student['gpa']}")

6.4 String Methods Quick Reference


Method Description Example Result
strip() Remove whitespace ' hi '.strip() 'hi'
split(sep) Split into list 'a,b'.split(',') ['a','b']
join(iter) Join with separator '-'.join(['a','b']) 'a-b'
replace(a,b) Replace substring 'hi'.replace('i','ello') 'hello'
find(s) Index of substring 'hello'.find('ll') 2
upper() All uppercase 'hi'.upper() 'HI'
lower() All lowercase 'HI'.lower() 'hi'
startswith(s) Check prefix 'Python'.startswith('Py') True
endswith(s) Check suffix '[Link]'.endswith('.py') True
count(s) Count occurrences 'aabaa'.count('a') 4
strip/lstrip/rstrip Remove chars '###hi###'.strip('#') 'hi'
isdigit() All digits? '123'.isdigit() True

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

7. Comprehensions

Python supports comprehension syntax for lists, dictionaries, and sets. Comprehensions are
faster than equivalent for-loop constructs and are central to idiomatic, professional Python.

7.1 List Comprehensions (covered in depth in Section 2.5)


Syntax: [ expression for item in iterable if condition ]

# Even numbers 0–20


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

# Celsius to Fahrenheit
celsius = [0, 10, 20, 30, 40]
fahrenheit = [(c * 9/5) + 32 for c in celsius]
# [32.0, 50.0, 68.0, 86.0, 104.0]

7.2 Dictionary Comprehensions (covered in Section 4.5)


Syntax: { key : value for item in iterable if condition }

7.3 Set Comprehensions


Syntax: { expression for item in iterable if condition }

# Unique lengths of words


words = ['cat', 'dog', 'elephant', 'cat', 'ant', 'dog']
lengths = {len(w) for w in words}
print(lengths) # {3, 8} (order may vary)

# First letters of names


names = ['Alice', 'Bob', 'Anna', 'Carol', 'Ben']
initials = {name[0] for name in names}
print(initials) # {'A', 'B', 'C'}

7.4 Generator Expressions


Generator expressions look like list comprehensions but use parentheses (). They produce items
lazily — one at a time — using almost no memory. Use them when you only need to iterate once
over large data.
# List comprehension — stores all 1 million values in memory
squares_list = [x**2 for x in range(1_000_000)]

# Generator expression — generates values on demand


squares_gen = (x**2 for x in range(1_000_000))

# Consume with next() or a for loop


print(next(squares_gen)) # 0
print(next(squares_gen)) # 1

# sum() accepts a generator — very memory-efficient


total = sum(x**2 for x in range(1_000_000))

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

7.5 Comparison: For Loop vs Comprehension


Approach Code Memory Speed Readability
for loop squares = [] for x in range(10): O(n) Slower Verbose
[Link](x**2)
Comprehension [x**2 for x in range(10)] O(n) Faster Concise
Generator (x**2 for x in range(10)) O(1) Fastest Concise

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

8. Choosing the Right Data Structure

Choosing the correct data structure is a fundamental programming skill. The wrong choice leads
to slow code, unnecessary complexity, and bugs. Use this section as a decision guide.

8.1 Decision Guide


If you need to... Use Why
Store an ordered collection that List Mutable, indexed, flexible
changes
Store fixed records (coordinates, Tuple Immutable, faster, signals intent
colours)
Look up values by a meaningful Dictionary O(1) key access
name/key
Store unique items with no Set Automatic deduplication
duplicates
Perform fast membership testing Set or Dict O(1) vs O(n) for list
Use a collection as a dict key Tuple or Frozenset Must be hashable
Process text / character sequences String Rich text methods
Work with large data one item at a Generator O(1) memory usage
time

8.2 Full Comparison Table


Feature List Tuple Dict Set String
Ordered Yes Yes Yes* No Yes
Mutable Yes No Yes Yes No
Duplicate values Yes Yes Values No Yes
Index access Yes Yes No No Yes
Key access No No Yes No No
Hashable (dict key) No Yes No No Yes
Membership O(1) No O(n) No O(n) Yes Yes No O(n)
Comprehension Yes No Yes Yes No
Typical use General Fixed Lookup Unique Text data
collections records tables items
* Dicts maintain insertion order from Python 3.7+

8.3 Common Mistakes to Avoid


Mistake Problem Fix
Using a list when Duplicates silently enter Use a set
uniqueness is needed
Using == to compare with Unreliable for NoneType Use 'is None'
None
Modifying a list while Skips elements Iterate over a copy: list(lst)
iterating over it unexpectedly

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

Forgetting the comma in a (42) is an int, not a tuple Write (42,)


single-element tuple
Direct key access without KeyError if key missing Use [Link](key, default)
.get()
Using {} for an empty set {} creates a dict, not a set Use set()
Comparing floats with == 0.1+0.2 != 0.3 due to Use abs(a-b) < 1e-9
IEEE 754

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

9. Practice Exercises

Work through these exercises in order. Exercises are graded: ★ = beginner, ★★ = intermediate,
★★★ = advanced.

9.1 Lists ★
Exercise 1
Given the list: temps = [22, 18, 25, 30, 15, 28, 20]
1. Sort the list in descending order.
2. Find the highest and lowest temperature using built-in functions.
3. Using a list comprehension, create a new list that contains only temperatures above 20.
4. Using a list comprehension, label each temperature 'Hot' if above 25, 'Warm' if 20–25,
'Cool' if below 20.

Exercise 2
Write a function flatten(matrix) that accepts a 2-D list (list of lists) and returns a single flat list
using a list comprehension.

9.2 Tuples ★
Exercise 3
You have a list of student records: records = [('Alice', 22, 88), ('Bob', 19, 75),
('Carol', 21, 92)]
5. Use a for loop with tuple unpacking to print each student in the format: Alice (age 22): 88
marks
6. Sort the records by score in descending order using sorted() with a lambda key.
7. Explain why you would use a tuple rather than a list for each student record.

9.3 Dictionaries ★★
Exercise 4
Given: grades = {'Alice': 90, 'Bob': 45, 'Carol': 82, 'Dave': 35, 'Eve': 71}
8. Using a dictionary comprehension, create a new dictionary containing only students who
passed (score >= 50).
9. Using a dictionary comprehension, normalise all scores to a 0–100 scale where the
highest score becomes 100.
10. Add a new student 'Frank' with a score of 68 without using update().
11. Safely access the score of a student 'Grace' who is not in the dictionary, returning 0 as
default.

Exercise 5 ★★
Write a function word_frequency(text) that accepts a string and returns a dictionary where
each key is a word and the value is how many times that word appears. Use .split() and a dict
comprehension or loop. Test with: 'the cat sat on the mat the cat'

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

9.4 Sets ★★
Exercise 6
You have two lists of students who enrolled in different courses:
python_students = ['Alice', 'Bob', 'Carol', 'Dave', 'Eve']
ml_students = ['Carol', 'Dave', 'Frank', 'Grace', 'Alice']
12. Find all students enrolled in BOTH courses.
13. Find students enrolled in Python but NOT ML.
14. Find all unique students across both courses.
15. Find students enrolled in one course but NOT both.

9.5 Mixed ★★★


Exercise 7 — Student Database
Build a student database using nested dictionaries. Write functions to:
16. add_student(db, student_id, name, scores_dict) — add a new student.
17. get_average(db, student_id) — return the student's average score across all subjects.
18. top_student(db) — return the name of the student with the highest average score.
19. passing_students(db, threshold=50) — return a list of names of students whose average is
above the threshold.

Test your database with at least 4 students, each with scores in 3 subjects.

9.6 Solutions — Selected


Exercise 1 — Solution
temps = [22, 18, 25, 30, 15, 28, 20]

# 1. Sort descending
sorted_temps = sorted(temps, reverse=True)
print(sorted_temps) # [30, 28, 25, 22, 20, 18, 15]

# 2. Max and min


print(max(temps), min(temps)) # 30 15

# 3. Only above 20
above_20 = [t for t in temps if t > 20]
# [22, 25, 30, 28]

# 4. Labels
labels = ['Hot' if t > 25 else 'Warm' if t >= 20 else 'Cool' for t in temps]
# ['Warm', 'Cool', 'Warm', 'Hot', 'Cool', 'Hot', 'Warm']

Exercise 5 — Word Frequency Solution


def word_frequency(text):
'''Return a dict of word: count pairs for each word in text.'''
words = [Link]().split()
return {word: [Link](word) for word in set(words)}

print(word_frequency('the cat sat on the mat the cat'))


# {'on': 1, 'the': 3, 'mat': 1, 'sat': 1, 'cat': 2}

Exercise 6 — Sets Solution

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

python_students = {'Alice', 'Bob', 'Carol', 'Dave', 'Eve'}


ml_students = {'Carol', 'Dave', 'Frank', 'Grace', 'Alice'}

# 1. Both courses
print(python_students & ml_students) # {'Alice', 'Carol', 'Dave'}

# 2. Python only
print(python_students - ml_students) # {'Bob', 'Eve'}

# 3. All unique students


print(python_students | ml_students) # all 7 students

# 4. Exactly one course (not both)


print(python_students ^ ml_students) # {'Bob', 'Eve', 'Frank', 'Grace'}

Python Data Structures — For Classroom Use Only


Introduction to Python | Data Structures Lecture Notes 2025–2026

10. Summary and Quick Reference

10.1 Data Structure Comparison


Structure Syntax Ordered Mutable Duplicates Hashable Best For
List [1,2,3] Yes Yes ✓ Yes No Ordered, changeable
collections
Tuple (1,2,3) Yes No ✗ Yes Yes Fixed records, dict keys
Dictionary {'a':1} Yes* Yes ✓ No No Key-value lookup
Set {1,2,3} No Yes ✓ No No Unique items, set
operations
Frozenset frozenset() No No ✗ No Yes Immutable unique items
String 'abc' Yes No ✗ Yes Yes Text processing

10.2 Best Practices


• Use descriptive variable names: student_scores, not ss or x.
• Prefer tuples for fixed data — it signals to readers that the data should not change.
• Use .get() on dicts to avoid KeyError when a key may not exist.
• Use sets for deduplication and membership testing over large datasets.
• Use list/dict/set comprehensions over for loops for cleaner, faster code.
• Never use {} for an empty set — always use set().
• Never compare floats with == — use abs(a - b) < 1e-9 instead.
• Use f-strings for all string formatting — they are readable and fast.
• Restart and Run All in Jupyter before submitting work — ensure cells run in order.

10.3 Further Reading


• Official Python Docs: [Link]/3/tutorial/[Link]
• Real Python — Python Data Structures: [Link]
• PEP 8 — Python Style Guide: [Link]/pep-0008/

— End of Lecture Notes —

Python Data Structures — For Classroom Use Only

You might also like