fruits = ["apple", "banana", "cherry", "date"]
print(fruits)['apple', 'banana', 'cherry', 'date']
Variables store single values. Data structures store collections of them. Python has three built-in types you’ll use constantly:
A list stores multiple items in order. Three things to know:
Square brackets [], items separated by commas:
Each item has a position called an index. Indexing starts at 0 (not 1):
Negative indices count from the end. fruits[-1] gives you the last item:
Adding elements with append():
Removing elements with remove() (removes the first match):
Changing an element by assigning to its index:
A for loop runs the same code for each item in a list:
I love apricot!
I love cherry!
I love date!
I love elderberry!
The variable name after for (here, fruit) is your choice. Python assigns each list item to it in turn. As with if/else blocks, the indented lines are the loop body.
Python also has while loops, which keep running as long as a condition is True. These are useful when you don’t know in advance how many iterations you need. We won’t use them in this lesson, but they’re worth knowing about. You can read more in the Python docs.
The in keyword checks whether an item exists in a list. After the modifications above, our list looks like this:
You’ll usually combine in with if/else:
No kiwi in this list.
| Function | What it does | Example |
|---|---|---|
len() |
Number of items | len([1, 2, 3]) → 3 |
sum() |
Sum of numeric items | sum([10, 20]) → 30 |
min() |
Smallest item | min([5, 3, 9]) → 3 |
max() |
Largest item | max([5, 3, 9]) → 9 |
sorted() |
Returns a new sorted list | sorted([3, 1, 2]) → [1, 2, 3] |
A set stores unique items with no guaranteed order. If a list is a numbered sequence where position matters, a set is a bag where you only care about what’s inside.
Curly braces {} or the set() function. Notice how duplicates are removed automatically:
You can also create a set from a list:
.add() inserts an element. .discard() removes one (without raising an error if it’s missing, unlike .remove()):
Sets support mathematical operations for comparing collections:
Union combines all elements from both sets:
Intersection keeps only elements in both sets:
Difference keeps elements in the first set but not the second:
A common pattern: convert a list to a set to remove duplicates, then back to a list.
A dictionary stores key-value pairs. You look up values by their key, like looking up a word in an actual dictionary.
{'name': 'Alice', 'age': 25, 'major': 'Computer Science'}
Keys must be unique and are typically strings or integers. Dictionaries are mutable.
Use square brackets or .get():
The difference: student["gpa"] raises a KeyError if the key doesn’t exist. student.get("gpa") returns None instead.
Update an existing value or add a new key by assigning to it:
{'name': 'Alice', 'age': 35, 'major': 'Computer Science', 'gpa': 3.8}
Remove entries with del or .pop(). .pop() also returns the removed value:
Loop over keys:
Loop over values with .values():
Loop over both with .items() (note the two variables):
Check if a key exists with in:
Major is not in the dictionary.
Python has another data structure called a tuple, written with parentheses: (1, 2, 3). Tuples behave like lists but are immutable (you can’t change their contents after creation). You’ll see them returned by functions like enumerate() and zip() in the bonus section below. We won’t cover them in depth here, but it’s useful to recognise the syntax when you encounter it.
These patterns come up often enough that they’re worth knowing now.
enumerate()enumerate() gives you both the index and the value on each iteration:
zip()zip() pairs up items from two or more lists:
Alice is 25 years old
Bob is 30 years old
Charlie is 35 years old
Use strict=True to catch mismatched list lengths (requires Python 3.10+, which Colab provides).
These combine arithmetic with assignment. You’ll see them in loops that accumulate values:
Total: 15
The full set of compound operators:
| Operator | Equivalent To | Description |
|---|---|---|
+= |
x = x + y |
Adds and assigns |
-= |
x = x - y |
Subtracts and assigns |
*= |
x = x * y |
Multiplies and assigns |
/= |
x = x / y |
Divides and assigns |
//= |
x = x // y |
Floor divides and assigns |
%= |
x = x % y |
Modulus and assigns |
**= |
x = x ** y |
Exponentiates and assigns |
Here’s a small example that combines dictionaries, loops, and string operations to draw a text-based bar chart of building heights in Madrid.
# heights in metres (approximate)
buildings = {
"Torre Cepsa": 55,
"Torre de Cristal": 64,
"Torre PwC": 40,
"Torre Emperador": 46,
"Torrespaña": 42,
}
# find the tallest so we can scale the bars to fit
max_height = max(buildings.values())
for name, height in buildings.items():
bar_length = int(height / max_height * 20) # scale to 20 characters wide
bar = "█" * bar_length
print(f"{name:>20} {bar} {height}m") Torre Cepsa █████████████████ 55m
Torre de Cristal ████████████████████ 64m
Torre PwC ████████████ 40m
Torre Emperador ██████████████ 46m
Torrespaña █████████████ 42m
Nothing here is new. The dictionary stores the data, the loop iterates through it, f-strings format the output, and string repetition ("█" * n) draws the bars. But combining them produces something visual and satisfying.
Reverse the list [1, 2, 3, 4].
Find the sum of all even numbers in the list [1, 2, 3, 4, 5, 6].
Merge [1, 2, 3] and [2, 3, 4] into a single list with no duplicates.
Merge the following two dictionaries. If a key appears in both, sum the values.
Expected result: {'a': 1, 'b': 5, 'c': 7, 'd': 5}
Given the list [1, 2, 2, 3, 3, 3, 4], count how many times each element appears. The result should be a dictionary: {1: 1, 2: 2, 3: 3, 4: 1}