Python + AI/ML · Tutorial 3 of 5
Python Lists and Dictionaries: the two structures you will use daily
By the FUTEAC Team · 31 October 2026 · 12 min read · Beginner
In short
Use a list when you need an ordered collection of items you reach by position — like marks in a class, where marks[0] is the first student's score. Use a dictionary when each value has a name — like a student record, where student["name"] is the name and student["city"] is the city. Lists answer "which position?"; dictionaries answer "which key?".
- A list keeps order and lets you index by position.
marks[0]is the first item,marks[-1]is the last, andmarks[1:4]takes a slice. - A dictionary stores pairs of keys and values. You look things up by name, not position:
student["city"]gives"Lahore". - Lists grow with
append; dictionaries grow by assigning a new key.marks.append(88)adds to the end;student["phone"] = "0300-1234567"adds a field. student.get("phone", "not provided")reads safely. If the key is missing, you get the default instead of a crash.- This tutorial feeds the Python Programming Foundations course (/course/python-programming-foundations/) and the Python Data Structures skill (/skill/python-data-structures/).
Before you start
What is a list — and how do I read one?
A list is an ordered collection, written with square brackets. It is the right choice when the *position* of each item matters — marks in roll-number order, tasks in the order you will do them, lines of a file in the order they were read.
marks = [72, 85, 90, 64, 78]
print("marks:", marks) # marks: [72, 85, 90, 64, 78]
print("first mark:", marks[0]) # first mark: 72
print("last mark:", marks[-1]) # last mark: 78
print("middle three:", marks[1:4]) # middle three: [85, 90, 64]
print("how many:", len(marks)) # how many: 5
print("average:", sum(marks) / len(marks)) # average: 77.8Expected output (exactly as printed):
marks: [72, 85, 90, 64, 78]
first mark: 72
last mark: 78
middle three: [85, 90, 64]
how many: 5
average: 77.8Three things to lock in: indexing starts at 0 (the first item is marks[0]), -1 counts from the end (a reliable way to grab the last item without knowing the length), and a slice like marks[1:4] takes positions 1, 2 and 3 — the end position is excluded. That "end excluded" rule catches every beginner once; now it will not catch you.
How do I add to a list and take a slice?
Lists grow from the end with append:
marks = [72, 85, 90, 64, 78]
marks.append(88)
print("after append:", marks) # after append: [72, 85, 90, 64, 78, 88]Expected output (exactly as printed):
after append: [72, 85, 90, 64, 78, 88]append takes exactly one argument — one item at a time. To combine two lists, use marks + more (which makes a new list) or marks.extend(more) (which adds each item of more to marks).
What is a dictionary — and why not just use two lists?
A dictionary stores key–value pairs, written with curly braces. It is the right choice when each value has a *name* you will search by — a student has a name, a city, and a marks list; a configuration has option names and their settings.
You could keep two lists — one of names, one of cities — and match them by position. That works until a record is deleted, or until you hand the data to someone else, and then the positions silently drift apart. A dictionary ties each value to its own key, so the pairing can never break.
student = {"name": "Ayesha", "city": "Lahore", "marks": marks}
print("student:", student)
# student: {'name': 'Ayesha', 'city': 'Lahore', 'marks': [72, 85, 90, 64, 78, 88]}
print("name:", student["name"]) # name: Ayesha
print("city via get:", student.get("city")) # city via get: Lahore
print("missing key via get:", student.get("phone", "not provided"))
# missing key via get: not providedExpected output (exactly as printed):
student: {'name': 'Ayesha', 'city': 'Lahore', 'marks': [72, 85, 90, 64, 78, 88]}
name: Ayesha
city via get: Lahore
missing key via get: not providedNotice two things. First, a dictionary value can be anything — here marks is a whole list living inside the dictionary, which is exactly how real data looks (JSON from an API is dictionaries and lists nested together). Second, reading a missing key with square brackets (student["phone"]) raises a KeyError and crashes the program, while get returns None — or the default you pass — instead. Use square brackets when the key *must* exist and you want a loud failure if it does not; use get with a default when it might be absent, like an optional phone number.
How do I add keys and read safely with `get`?
Adding a field is just an assignment:
student["phone"] = "0300-1234567"
print("all keys:", list(student.keys()))
# all keys: ['name', 'city', 'marks', 'phone']Expected output (exactly as printed):
all keys: ['name', 'city', 'marks', 'phone']Assigning to an existing key overwrites its value; assigning to a new key adds it. There is no separate "add" step, which is why beginners sometimes do not realise they just created a key — watch your spelling, because student["name"] = ... updates the name while student["nmae"] = ... silently adds a typo'd key beside it.
When do I use a list and when do I use a dictionary?
Ask one question: am I finding things by position, or by name?
- By position → list. Marks in roll-number order, the last five logins, a shopping basket. Order matters and you will index, slice, or loop through in order.
- By name → dictionary. A student record, a product with its price, settings with option names. The lookup is by key and order does not matter (a dictionary *does* remember insertion order, but you should not rely on it for meaning).
Very often the answer is both: a *list of dictionaries* is how real datasets are shaped — each row of a table is a dictionary, and the table itself is a list:
students = [{"name": "Ayesha", "marks": 85}, {"name": "Bilal", "marks": 72}]
for s in students:
print(s["name"], "scored", s["marks"])
# Ayesha scored 85
# Bilal scored 72Expected output (exactly as printed):
Ayesha scored 85
Bilal scored 72If you only take one pattern from this tutorial, take this one: dictionaries for rows, a list for the table.
Worked example: a tiny class-records program
Here is one short program that uses everything above — it builds records, grows them, and prints a summary:
students = [
{"name": "Ayesha", "marks": [72, 85, 90]},
{"name": "Bilal", "marks": [64, 78, 81]},
]
for s in students:
marks = s["marks"]
average = sum(marks) / len(marks)
s["average"] = round(average, 1)
print(s["name"], "— average:", s["average"])
print()
print("top student:", max(students, key=lambda s: s["average"])["name"])Expected output (exactly as printed):
Ayesha — average: 82.3
Bilal — average: 74.3
top student: AyeshaStep through it: each s is a dictionary, s["marks"] pulls its list, the average is computed and stored back with s["average"] = ... (a new key added by assignment, as above), and max(...) with a key function picks the dictionary with the highest average — whose "name" we then print. This is not a toy pattern: read a CSV file into a list of dictionaries and you have the whole shape of the Data Cleaning work in the course's project, "Build a Personal Expense Tracker in Python".
Try it yourself
1. Build a book dictionary with keys title, author and pages for a book you own. Print the title with square brackets, then read the publisher with get("publisher", "unknown"). 2. Make a list of three dictionaries — name and age for three family members — then loop and print "<name> is <age>" for each. 3. Extend the class-records program: add a third student, and print only the students whose average is 75 or above.
Continue in the free course: Python Programming Foundations →
Common mistakes
- Indexing from 1.
marks[1]is the *second* item. If your "first" result looks off by one, you started counting from 1 — Python starts from 0. - Reading a missing key with square brackets.
student["phone"]before the key exists raisesKeyError. Usestudent.get("phone", "not provided")when the key might be absent. - Creating a typo'd key by assignment.
student["nmae"] = "Ayesha"does not fix the name — it adds a second, wrongly spelled key. Check the spelling of the key, not just the value. appendinside a print.print(marks.append(88))printsNone—appendchanges the list in place and returns nothing. Print the list on the next line.- Two lists instead of a dictionary. Keeping names in one list and marks in another works until one gets longer than the other. Pair them in dictionaries from the start.
Frequently asked questions
What is the difference between a list and a tuple?
A tuple is a list that cannot change after creation — written with parentheses, like (72, 85). Lists are for data that grows or updates (marks through the term); tuples are for fixed values (a date of birth, coordinates). The course lesson "Lists and Tuples" covers this in depth.
How do I remove an item from a list or dictionary?
For a list, marks.remove(64) removes the value 64, and del marks[0] removes the first item. For a dictionary, del student["phone"] removes the key and its value. marks.pop() removes and returns the last item — handy when the removed value is needed.
Can a dictionary key be a number?
Yes — keys just need to be unchangeable (immutable): strings, numbers, and tuples all work. Lists cannot be keys because they can change. String keys are the convention for records.
What does KeyError mean, exactly?
It means you asked for a dictionary key that does not exist with square-bracket syntax — for example student["email"] before any "email" was assigned. Read the error: it names the missing key. Decide whether the key should exist (fix the code) or might legitimately be missing (use get with a default).
How do lists and dictionaries connect to the next tutorials?
The next tutorial in this series, Cleaning Data with pandas: missing values and duplicates, reads data into structures exactly like the "list of dictionaries" above. And the course module "Decisions, Loops and Data Collections" tests all of this in the "Module Quiz: Flow and Collections". ---
Follow the Python + AI/ML Beginner Roadmap
Learn Python from zero and take your first steps into AI and machine learning. Free, step by step, at your pace.
View the Roadmap