The PCAP-31-03 exam domain on collections tests how you organise and manipulate groups of data. Lists, tuples, and dictionaries are the fundamental tools Python gives you to store multiple items, and knowing when to use each one — and how to use their built-in methods — directly determines whether your code works correctly or crashes with a confusing error. This chapter gives you the mental model and the hands-on knowledge you need to answer exam questions about creating, accessing, modifying, and iterating over these three core collection types.
Jump to a section
A simple way to picture Collections: Lists, Tuples, and Dictionaries
A head chef runs a busy restaurant kitchen. To keep everything organised, she relies on a custom recipe box with three different sections. The first section is a ring-bound notebook where she writes down her standard recipes in a specific order — the starter, then the main course, then the dessert. She can flip pages to add a new recipe between any two existing ones, or tear one out to remove it. She can also change an ingredient list whenever she wants. This notebook is like a Python list: ordered, changeable, and flexible.
The second section is a sealed, laminated card with the restaurant's signature dish — a dish that never changes. The chef can read the ingredients and instructions, but she cannot modify the card. If she wants a different version, she must create a whole new card. This is like a Python tuple: ordered and unchangeable, perfect for fixed data like days of the week or configuration constants.
The third section is a magnetic board with labelled jars for each ingredient: one jar labelled 'flour', another labelled 'sugar'. The chef can quickly grab the flour jar by its label without counting through jars. She can add a new jar with a new label, or remove one entirely. This is like a Python dictionary: it stores pairs of labels (keys) and contents (values), and you retrieve items by their label, not by their position. The chef uses the appropriate section depending on the task — the notebook for a menu she is still perfecting, the laminated card for the fixed signature dish, and the magnetic board for quick ingredient look-up by name.
In Python, a collection is a single container that holds multiple pieces of data. Instead of having ten separate variables like item1, item2, item3, you can have one variable called shopping_list that contains all ten items. Python gives you three primary built-in collections for everyday use: lists, tuples, and dictionaries. Each has its own personality, and choosing the right one is a key skill for the PCAP-31-03 exam.
A list is an ordered, mutable (changeable) collection. You create a list with square brackets: fruits = ['apple', 'banana', 'cherry']. The items stay in the order you put them in. You can access the first item with fruits[0], the second with fruits[1], and so on. Because lists are mutable, you can change an item: fruits[1] = 'blueberry'. You can add items with append() or insert(), and remove items with remove() or pop(). Lists are the workhorse collection — you use them when you have a sequence of items that might need to change, like a to-do list or a set of test scores you are still collecting.
A tuple is an ordered, immutable (unchangeable) collection. You create a tuple with parentheses: weekdays = ('Monday', 'Tuesday', 'Wednesday'). Like a list, it preserves order and you access items by index with weekdays[0]. The critical difference is that once you create a tuple, you cannot change, add, or remove items. Why would you ever want that? Tuples are safer for data that should never change — for example, the days of the week, the RGB values for a colour, or a set of configuration constants. Tuples also use less memory and can be used as dictionary keys (lists cannot). The exam loves to test whether you know that attempting tuple[0] = 'newvalue' will raise a TypeError.
A dictionary is an unordered (in older Python versions), key-value pair collection. You create a dictionary with curly braces: student = {'name': 'Alice', 'age': 22, 'course': 'Physics'}. Instead of accessing items by a numeric index, you access them by a key: student['name'] returns 'Alice'. The key must be an immutable type (string, number, tuple), and the value can be anything. Dictionaries are mutable: you can add a new key-value pair with student['grade'] = 'A', change an existing value with student['age'] = 23, or delete a key with del student['course']. Use dictionaries when you have data that is best looked up by a descriptive label — a phonebook, a product catalogue, or a settings configuration.
All three collections share some common operations. You can check the length with len(). You can check if an item exists with the 'in' keyword: 'apple' in fruits returns True or False. You can loop through them with a for loop: for fruit in fruits: print(fruit). But dictionaries need a special pattern: for key in student: print(key, student[key]) or using the .items() method.
Key methods you must know for the exam:
List methods: append(item) adds to the end. insert(index, item) inserts at a position. remove(item) removes the first matching item. pop(index) removes and returns the item at that index. sort() sorts the list in place. reverse() reverses the order.
Tuple methods: tuples have only two built-in methods — count(item) returns how many times an item appears, and index(item) returns the position of the first occurrence. That is it.
Dictionary methods: keys() returns a view of all keys. values() returns a view of all values. items() returns a view of key-value tuples. get(key, default) safely retrieves a value or returns a default if the key doesn't exist (avoiding a KeyError). update(other_dict) merges another dictionary into the current one. pop(key) removes and returns the value for that key.
A common exam scenario is converting between these types. For example, list(my_tuple) creates a list from a tuple’s items. tuple(my_list) creates a tuple from a list’s items. dict(my_list_of_pairs) creates a dictionary from a list of two-item tuples like [('a',1), ('b',2)].
Remember that lists and dictionaries are mutable — the exam often presents code that modifies a list inside a function and asks whether the original list outside the function is changed. (It is, because the reference is passed.) Tuples are immutable — passing a tuple to a function guarantees the data stays intact.
Creating a List, Tuple, and Dictionary
Start by declaring each collection with its correct syntax. For a list: my_list = [1, 2, 3]. For a tuple: my_tuple = (1, 2, 3). For a dictionary: my_dict = {'one': 1, 'two': 2}. Use the correct brackets — mixing them up causes a syntax error or creates the wrong type.
Accessing Items by Index or Key
For lists and tuples, use a zero-based index inside square brackets: my_list[0] returns 1. For dictionaries, use the key: my_dict['one'] returns 1. Trying to access a non-existent index in a list or tuple raises an IndexError; a missing key in a dictionary raises a KeyError.
Modifying a Collection
Lists and dictionaries allow modification: my_list[0] = 10 updates the first element; my_dict['three'] = 3 adds a new key-value pair. Tuples forbid modification: my_tuple[0] = 10 raises a TypeError. This step highlights the core difference between mutable and immutable types.
Adding and Removing Items
For lists, use append() to add to the end, insert() to add at a specific position, remove() to delete by value, and pop() to delete by index. For dictionaries, assign a new key to add: my_dict['new'] = 5, and use del my_dict['key'] or pop('key') to remove. Tuples cannot have items added or removed — you must create a new tuple.
Looping Through a Collection
Use a for loop: for item in my_list: processes each element. For dictionaries, use for key in my_dict: or for key, value in my_dict.items(): to get both key and value. Looping is how you process all items without manually indexing each one.
Using Built-in Methods and Functions
Apply methods like len(), sorted(), .count(), .index(), .keys(), .values(), and .items() depending on the collection type. Each method has a specific purpose: len() works on all three, .keys() only on dictionaries, .count() on lists and tuples. Knowing which methods work on which type is essential for the exam.
An IT professional working in data analysis or backend development uses lists, tuples, and dictionaries every single day. Consider a real scenario: a developer is building a system for an online bookstore. They need to manage a catalogue of books, a shopping cart for a customer, and a set of fixed categories.
First, the developer defines the book categories as a tuple: categories = ('Fiction', 'Non-Fiction', 'Science', 'History'). Why a tuple? Because the categories are fixed — the company does not add or remove categories often, and using an immutable tuple prevents accidental changes. If a bug elsewhere tries to do categories[0] = 'Romance', the program instantly crashes with a TypeError, alerting the developer to the problem rather than silently corrupting data.
Second, the developer stores the catalogue as a list of dictionaries. Each book is a dictionary with keys like 'title', 'author', 'price', 'category'. The entire catalogue is a list: catalogue = [{'title': 'Python Basics', 'author': 'Smith', 'price': 29.99, 'category': 'Science'}, ...]. The list allows the developer to add new books easily with catalogue.append(new_book), remove outdated books with catalogue.remove(old_book), or sort by price with catalogue.sort(key=lambda book: book['price']). The dictionary structure inside each book makes it simple to look up the author with book['author'] or update the price with book['price'] = 24.99.
Third, the shopping cart is a list of dictionaries, but with an extra twist: the developer might use a dictionary to store the cart, with the product ID as the key and the quantity as the value. This way, adding an item is as simple as cart[product_id] = cart.get(product_id, 0) + 1. No need to loop through the entire list to find duplicates.
What does the developer actually do step by step? - They initialise the categories as a tuple at the top of the module, ensuring no code can accidentally modify them. - They build the catalogue list by reading from a database, appending each book dictionary to the list. - They write a function to search the catalogue: for book in catalogue: if search_term in book['title']: results.append(book). - They write a function to add to cart: cart[product_id] = cart.get(product_id, 0) + 1. - They write a function to calculate the total: for product_id, quantity in cart.items(): total += catalogue[product_id]['price'] * quantity. - They use tuple unpacking when looping over dictionary items: for key, value in student.items(): ...
In a real business context, choosing the right collection type affects code readability, performance, and bug resistance. Using a list where a tuple should be used leads to accidental mutations. Using a list where a dictionary should be used forces slow linear searches (O(n)) instead of fast key lookups (O(1) average). The PCAP-31-03 exam expects you to understand these trade-offs.
The PCAP-31-03 exam tests your understanding of collections through multiple-choice and single-answer questions that often involve reading a short piece of code and predicting the output or the error. There are very few trick questions, but there are definite trap patterns.
First, the exam loves to test mutability vs. immutability. You will see a question like: "What is the output of this code? my_tuple = (1, 2, 3); my_tuple[1] = 10; print(my_tuple)" The answer is a TypeError. They want you to recognise that tuples cannot be changed. A variant uses a list inside a tuple: my_tuple = ([1, 2], 3); my_tuple[0].append(4). That works, because the tuple holds a reference to the list, and the list itself is mutable. Changing the list's contents does not change the tuple itself.
Second, they test dictionary key constraints. They will ask: "Which of the following can be used as a dictionary key?" Options might include a list, a tuple, a string, an integer. The correct answer is any immutable type: tuples, strings, numbers. Lists and dictionaries cannot be keys because they are mutable.
Third, they test method return values. For example, list.sort() sorts the list in place and returns None, while sorted(list) returns a new sorted list without modifying the original. The exam loves to ask: "What is printed? my_list = [3,1,2]; print(my_list.sort())" The answer is None, not [1,2,3].
Fourth, they test slicing. They will give you a list and ask for the output of a slice like my_list[::-1] (reverses the list) or my_list[1:4] (elements at indices 1,2,3). Understand that slicing returns a new list (or tuple if slicing a tuple).
Fifth, they test the difference between remove() and pop(). remove('apple') deletes the first occurrence of the value, while pop(2) deletes and returns the element at index 2. Using pop() without an argument removes and returns the last element.
Key concepts to memorise:
List: mutable, ordered. Methods: append, insert, remove, pop, sort, reverse, index, count, extend.
Tuple: immutable, ordered. Methods: index, count.
Dictionary: mutable, unordered (in Python 3.6 and earlier; insertion-ordered in Python 3.7+). Methods: keys, values, items, get, update, pop, popitem, clear.
The 'in' operator works on all three: checks membership in the collection (checks keys in a dictionary).
len() returns the number of items.
A dictionary comprehension and list comprehension are advanced topics they may test.
Common traps:
Confusing list.sort() with sorted().
Thinking a tuple can be changed.
Using a mutable type as a dictionary key.
Expecting pop() or remove() on a tuple (they don't exist).
Forgetting that [] is an empty list, () is an empty tuple, {} is an empty dictionary.
Thinking that dict.items() returns a list (it returns a view object, but for loop purposes it works similarly).
The exam typically includes 3-5 questions on collections, spread across multiple objectives. You need to be comfortable reading code and predicting output, not just memorising definitions.
A list is mutable, ordered, and defined with square brackets — use it when you need a flexible sequence of items.
A tuple is immutable, ordered, and defined with parentheses — use it for data that must never change, like days of the week or configuration constants.
A dictionary stores key-value pairs in curly braces and is accessed by key, not by index — use it for fast lookups by label, like a phonebook.
Only immutable types (strings, numbers, tuples) can be dictionary keys — lists and dictionaries themselves cannot be keys.
The list.sort() method sorts in place and returns None, while the sorted() function returns a new sorted list — they are not interchangeable.
The 'in' keyword checks membership: in a list it checks values, in a dictionary it checks keys (not values).
Tuples have only two methods: count() and index() — all other operations that modify the tuple are forbidden.
Dictionary methods get() and pop() are safer than direct indexing because they allow a default value and avoid KeyError exceptions.
These come up on the exam all the time. Here's how to tell them apart.
List
Mutable: items can be added, removed, or changed
Uses square brackets []
Has methods like append(), remove(), sort()
Tuple
Immutable: items cannot be changed after creation
Uses parentheses ()
Only has methods count() and index()
List
Items accessed by numeric index
Stores single values in sequence
Useful for ordered sequences where order matters
Dictionary
Items accessed by key (any immutable type)
Stores key-value pairs
Useful for lookups by descriptive label
Tuple
Immutable
Items accessed by numeric index
Cannot be used as a dictionary key if it contains mutable items
Dictionary
Mutable (the dictionary itself, but keys must be immutable)
Items accessed by key
Keys themselves can be tuples (if they are immutable)
list.sort()
Modifies the list in place
Returns None
Only works on lists
sorted()
Returns a new sorted list
Does not modify the original
Works on any iterable (list, tuple, string, etc.)
dict[key]
Raises KeyError if key does not exist
Direct assignment works for setting values
Faster than .get() for existing keys
dict.get(key)
Returns None (or default) if key does not exist
Cannot be used on the left side of assignment
Safer for accessing optional data
Mistake
A tuple is just a list that you cannot change, so it's the same as a list in all other ways.
Correct
A tuple is immutable, but it also has a fixed hash value, which means it can be used as a dictionary key, whereas a list cannot. Tuples also use less memory and are faster to create than lists.
The surface similarity (both ordered and index-based) leads beginners to think they are interchangeable in all contexts except mutation.
Mistake
A dictionary remembers the order of its items only from Python 3.7 onwards, so you can rely on order always being preserved.
Correct
While CPython 3.6+ and the official language spec from 3.7+ guarantee insertion order, exam questions may assume classic unordered behaviour for earlier versions. You should not write code that depends on dictionary order without being certain of the Python version.
Casual reading about Python history conflates implementation details with language guarantees.
Mistake
The 'in' keyword checks if a value exists in a dictionary the same way it checks a list.
Correct
In a dictionary, 'in' checks if a key exists, not a value. To check for a value, you must use 'value in dict.values()'.
Beginners assume the syntax is uniform across all types, but the semantics differ because dictionaries are key-value stores.
Mistake
Using pop() on a dictionary will always remove and return the most recently added item.
Correct
dict.pop() requires a key as an argument and removes that specific key-value pair. The method popitem() removes and returns the last inserted item (in Python 3.7+), but pop() without a mandatory key argument will raise a TypeError.
The name 'pop' is familiar from lists, where it optionally accepts an index and defaults to the last element, causing confusion with dictionaries.
Mistake
You can use a list or another dictionary as a dictionary key as long as you don't modify it afterwards.
Correct
Dictionary keys must be hashable (immutable). Lists and dictionaries are not hashable because they are mutable, regardless of whether you actually modify them. Python raises a TypeError at the point of assignment.
Beginners think about runtime behaviour rather than the type system's static requirement for hashability.
Mistake
The sort() method returns the sorted list, just like sorted() does.
Correct
list.sort() sorts the list in place and returns None. The sorted() built-in function returns a new sorted list and leaves the original unchanged. These are two different operations with different return values.
The naming similarity and the fact that both rearrange items lead beginners to assume identical behaviour.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
A dictionary key must be hashable (immutable) because Python uses the key's hash value to store and look up the key-value pair efficiently. Lists are mutable, so their hash could change, which would break the dictionary's internal structure. Tuples, strings, and numbers are immutable and therefore hashable, so they can be used as keys.
append() adds its argument as a single element to the end of the list, even if the argument is itself a list (so you get a nested list). extend() iterates over its argument and adds each element individually to the list. For example, [1,2].append([3,4]) results in [1,2,[3,4]], while [1,2].extend([3,4]) results in [1,2,3,4].
Use a tuple when the sequence of items should never change — for example, days of the week, RGB colour values, fixed configuration constants, or any data that represents a record (like a row from a database that you don't want accidentally modified). Tuples also use less memory, can be used as dictionary keys, and clearly signal to other developers that the data is constant.
dict.get(key, default) tries to retrieve the value for key from the dictionary. If the key exists, it returns the value. If the key does not exist, it returns the default value instead of raising a KeyError. This is useful for safely accessing optional keys, especially when working with data that might be missing.
The tuple itself is immutable — you cannot add, remove, or replace items in the tuple. However, if one of the items in the tuple is a mutable object (like a list), you can modify that list's contents. For example, t = ([1,2], 3); t[0].append(4) works and results in ([1,2,4], 3). The tuple still holds the same list object, but the list's internal state changed.
pop(index) removes and returns the element at the specified index. If no index is given, it removes and returns the last element. remove(value) removes the first occurrence of the specified value from the list. If the value is not found, remove() raises a ValueError. Both modify the list in place.
Use the .items() method inside a for loop: for key, value in my_dict.items(): print(key, value). This returns each key-value pair as a tuple, which you can unpack directly into the key and value variables. You can also loop with for key in my_dict: to get only keys, then use my_dict[key] to get values, but .items() is more efficient and readable.
You've finished Collections: Lists, Tuples, and Dictionaries. Continue through the PCAP-31-03 study guide to build a complete picture of the exam.
Done with this chapter?