Collections
- Lesson 5
- 40 min
- Module 2: Values and control flow
Lesson 5 of 18 · Python for Practical AI EngineeringCollections
1. Computer and environment basics
2. Values and control flow
3. Functions and program structure
4. Files, data and external services
5. Debugging and reliability
6. From notebook to maintainable project
What you will be able to do
Keep a set of support tickets in one variable, with a record for each ticket, and go through them one by one. Every program that processes data, from this course’s ticket-cleaner to a model’s training data, starts with this structure.
NotebookDo this lesson in a notebook
The notebook has every example, task and check of this lesson, with the instructions. It needs no install and no local project: only Python. Read the explanations here, and run the code there.
Colab and Kaggle open your own copy. They need a free Google or Kaggle account. Stuck? See the solution notebook.
Before you startWhat to know and to have ready
What you need to know
str,int,float,boolandNone, from Basic values.- How to read a state table, from Basic values: A variable can change.
What you need on your computer (only for the local route; the notebook and the boxes on this page need none of it)
- Nothing new. The boxes run Python in your browser. To run the code in a file instead, use your project with its environment active, from Isolate dependencies: Guided practice.
Tested with Python 3.14 (terminal) and Pyodide 314.0 (browser). The notebook was tested in Jupyter.
Four kinds of collection
Section titled “Four kinds of collection”A collection is one value that holds other values. Python has four main kinds. Each one fits a different job:
| Kind | Example | Use it when |
|---|---|---|
| list | ["open", "closed", "open"] |
The order matters, and items can repeat. You can add and remove items. |
| tuple | ("T-1001", "open") |
A small, fixed group of values that belong together. It cannot change. |
| set | {"billing", "login"} |
You need each value only once, and the order does not matter. |
| dictionary | {"id": "T-1001", "status": "open"} |
You look up a value by a name (a key). |
Most of the work in this course uses two of them together: a list of dictionaries. Each dictionary is one ticket, and the list holds all the tickets.
Lists: items in order
Section titled “Lists: items in order”A list is a sequence of values in square brackets. Each item has a position, called its index. The index starts at 0, not 1:
statuses = ["open", "closed", "open", "pending"]| Code | Result | Meaning |
|---|---|---|
statuses[0] |
"open" |
The first item. |
statuses[1] |
"closed" |
The second item. |
statuses[-1] |
"pending" |
The last item. Negative indexes count from the end. |
len(statuses) |
4 |
The number of items. The last index is always len - 1. |
statuses[1:3] |
["closed", "open"] |
A slice: from index 1 up to, but not including, index 3. |
statuses.append("open") |
(changes the list) | Adds an item at the end. Now len(statuses) is 5. |
Why does the index start at 0? The index counts how many items come before the item. The first item has zero items before it.
Go through every item
Section titled “Go through every item”To do something with each item, use a for loop:
for status in statuses: print(status)Python gives the name status to the first item and runs the indented line. Then it gives status the next item, and runs the line again, until there are no more items. The line after for must be indented (four spaces), and the for line ends with :. The indent shows which lines are inside the loop. You learn more about loops in the next lesson.
Dictionaries: values by name
Section titled “Dictionaries: values by name”A list finds a value by its position. A dictionary finds a value by a key: a name that you choose. Each entry is a key and a value, with : between them:
ticket = {"id": "T-1001", "status": "open", "category": "billing", "priority": 2}| Code | Result | Meaning |
|---|---|---|
ticket["category"] |
"billing" |
The value for the key "category". |
ticket["assignee"] |
error: KeyError: 'assignee' |
The key does not exist. |
ticket.get("assignee") |
None |
Like [ ], but gives None when the key does not exist. |
ticket.get("assignee", "nobody") |
"nobody" |
Gives your default value when the key does not exist. |
ticket["status"] = "closed" |
(changes the dictionary) | Changes a value, or adds the key if it is new. |
A dictionary is a good fit for a record: the keys are the field names, so ticket["priority"] explains itself. With a list, ticket[3] does not.
To go through every key and value, loop over .items(). Each step gives you two values, a key and its value:
for key, value in ticket.items(): print(key, "=", value)id = T-1001status = opencategory = billingpriority = 2Tuples and sets
Section titled “Tuples and sets”A tuple is like a list, in round brackets, but it cannot change after you make it. Use it for a small group of values that belong together, such as a pair. You can unpack a tuple into separate names in one line:
pair = ("T-1001", "open")ticket_id, status = pair # ticket_id is "T-1001", status is "open"A set keeps each value only once. Make one from a list to find the different values in it, and use in to check if a value is there:
categories = set(["billing", "login", "billing", "shipping"])print(categories) # {'billing', 'login', 'shipping'}, in any orderprint("login" in categories) # TrueA set has no order, so it can print the items in a different order on your computer. Use sorted(categories) when you need a fixed order. in also works on lists, strings and dictionary keys.
Worked example: a list of ticket records
Section titled “Worked example: a list of ticket records”Here are the six tickets that the rest of this module uses. Read the code from the outside in: a list ([ ]) with six dictionaries ({ }) in it.
Run Python in your browser
Explore the tickets
Before you press Run, predict the first three lines of the output. Then run it and compare.
Tab adds four spaces. Press Esc, then Tab, to leave the box. Ctrl+Enter runs the code.
tickets[-1]["category"] has two steps. tickets[-1] gives the last dictionary. ["category"] then gets one value from that dictionary. Read it from left to right.
Guided practice: answer questions about the tickets
Section titled “Guided practice: answer questions about the tickets”Use the same six tickets. Each step asks for one value. Write the code in the box, under the list.
- Show the status of the third ticket (
T-1003). Expected output:open. - Make a set of all the categories, then show it sorted. Expected:
['billing', 'login', 'shipping']. - Check if any ticket has the category
"refund". Expected:False. - Change the status of the first ticket to
"closed", then show the whole first ticket.
Run Python in your browser
Guided practice
Steps 1 and 2 are done for you. set() makes an empty set, and .add() puts one value in it. Do steps 3 and 4 yourself.
Tab adds four spaces. Press Esc, then Tab, to leave the box. Ctrl+Enter runs the code.
Show the answers for steps 3 and 4
# 3. Is there a "refund" ticket?print("refund" in categories)
# 4. Close the first ticket, then show it.tickets[0]["status"] = "closed"print(tickets[0])Two names, one list
Section titled “Two names, one list”This part explains one of the most common surprises in Python. = does not copy a value. It gives the value another name. Look at this code:
tickets = ["T-1001", "T-1002"]backup = ticketstickets.append("T-1003")print(backup)Most people expect backup to have two items. It has three. Here is the state after each line:
| After line | tickets refers to |
backup refers to |
The list itself |
|---|---|---|---|
| 1 | list A | (not yet) | A: ["T-1001", "T-1002"] |
| 2 | list A | list A | A: ["T-1001", "T-1002"] |
| 3 | list A | list A | A: ["T-1001", "T-1002", "T-1003"] |
There is only one list. backup = tickets made a second name for it, so a change through one name is visible through the other. The same is true for dictionaries and sets. It is not a problem for numbers and strings, because they cannot change: hours = hours + 2 makes a new number.
To make a real copy, call .copy(): backup = tickets.copy(). Now backup is a new list with the same items, and append changes only one of them.
Run Python in your browser
Predict, then run
Write down the three numbers that you expect. Then press Run.
Tab adds four spaces. Press Esc, then Tab, to leave the box. Ctrl+Enter runs the code.
Your turn: a lookup by ID
Section titled “Your turn: a lookup by ID”You have the six tickets in a list. A colleague asks for tickets by ID, many times a day. Make a dictionary by_id whose keys are the ticket IDs and whose values are the ticket records. Then by_id["T-1004"]["status"] must give "pending".
Run Python in your browser
Your turn: build by_id
Start with an empty dictionary, and add one entry for each ticket with a loop.
Tab adds four spaces. Press Esc, then Tab, to leave the box. Ctrl+Enter runs the code.
Show one answer
by_id = {}for ticket in tickets: by_id[ticket["id"]] = ticketEach step of the loop adds one key (the ticket’s ID) with the whole record as its value. A lookup by key is fast, even with a million tickets, because a dictionary does not search through the items one by one.
Common mistake
IndexError and KeyError
Symptom: the program stops with one of these errors:
IndexError: list index out of rangeKeyError: 'assignee'Cause: you asked for an item that is not there. IndexError means that the position is too large: a list with 6 items has the indexes 0 to 5, so tickets[6] does not exist. KeyError means that the dictionary has no such key. The key in the message shows what Python looked for. Check the spelling and the capital letters: "Status" and "status" are different keys.
Fix:
- Print what is there:
print(len(tickets))for a list,print(ticket.keys())for a dictionary. - For a list, use an index below
len(...), or-1for the last item. - For a dictionary key that can be missing, use
.get("key"), and decide what to do when the result isNone.
Check your understanding
Predict the output: statuses = ["open", "closed"]; same = statuses; same.append("pending"); print(len(statuses))
Show the answer
3. same = statuses does not copy the list. Both names refer to one list, so append through same changes the list that statuses refers to. Use statuses.copy() when you need a separate list.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Check your understanding
Which collection fits each job? (a) The six tickets in the order they arrived. (b) The different categories that appear. (c) One ticket's fields. (d) A ticket ID and its new status, passed together.
Show the answer
(a) A list: the order matters. (b) A set: each category only once. (c) A dictionary: you look up fields by name. (d) A tuple: two values that belong together and do not change.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Recap
- A list keeps items in order. The index starts at
0, and-1is the last item. - A dictionary finds a value by its key. Use
.get()when a key can be missing. - A tuple is a fixed group of values. A set keeps each value once, with no order.
for item in collection:runs the indented lines once for each item.=gives a value another name. It does not copy. Use.copy()for a separate list or dictionary.
Next, you make decisions with if, and use loops to filter the tickets and count them by category.
Next: Decisions and repetition