Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Open In Colab Open In Kaggle

This notebook assembles the everyday machinery of Python: the built-in containers (list, tuple, dict), the statements that drive decisions and repetition, and the functions that keep code organised and reusable.

Subchapter 1.1 handled one measurement at a time. Here we keep a small catalogue of weather stations, each with an elevation and a few daily mean temperatures, carry it through the whole notebook, and close with a generated-code bug that is silent until the function is called a second time.

The Sphinx Observatory at Jungfraujoch, above a sea of clouds

Figure 1:Sphinx Observatory, Jungfraujoch — the station behind this book’s running example. Photo by Julius Silver, via Wikimedia Commons, licensed under CC BY-SA 4.0.

1.2.1 Data Structures

Lists

A list is an ordered, mutable sequence — the default container for a series of measurements. We can create lists by separating different items with commas in square brackets: [Item1, Item2, Item3]. Lists come with built-in methods to modify their contents, such as .append() to add an item to the end, .insert() to add at a specific position, and .remove() to delete a specific value.

[-1.9, -2.3, -1.1, 1.2, -0.8, -3.1]
-1.9 -3.1
[-2.3, -1.1]
6

Tuples

A tuple is an immutable sequence. You need a tuple instead of a list when the data represents a fixed entity (like a coordinate pair or a date) where accidental modification of a single element would render the entire record physically invalid.

46.5475 7.9853

Dictionaries

A dictionary maps unique, immutable keys to values. It is written with braces, as {key: value} pairs separated by commas:

{
    "key_1": value_1,
    "key_2": value_2,
}

This structure provides very fast lookup by name or id, rather than by sequential position.

You can look up an element using square brackets, add new key-value pairs by assignment, and remove elements using the del keyword.

Jungfraujoch
Jungfraujoch
Warning: 'dates' key not found!
{'name': 'Jungfraujoch', 'elevation_m': 3571, 'coordinates': (46.5475, 7.9853), 'readings_celsius': [-2.3, -1.1, 0.4, 1.2, -0.8], 'country': 'Switzerland'}
{'name': 'Jungfraujoch', 'elevation_m': 3571, 'readings_celsius': [-2.3, -1.1, 0.4, 1.2, -0.8], 'country': 'Switzerland'}
dict_items([('name', 'Jungfraujoch'), ('elevation_m', 3571), ('readings_celsius', [-2.3, -1.1, 0.4, 1.2, -0.8]), ('country', 'Switzerland')])

1.2.2 Control Flow

Code normally runs linearly from top to bottom. Control flow allows a program to make decisions based on data values (conditional statements), repeat operations for multiple elements (loop statements), and interrupt or skip operations (control statements).

Decisions: if, elif, else

Here, we use conditional statements to combine relational operators and logical operators so that a program can have different information flow according to some conditions. In other words, some code snippets are executed only if some conditions are satisfied.

cold

Repetition: for, while

We use loop statements to execute code multiple times, for instance, applying an algorithm to every item in a list. In Python, for loops iterate over a sequence, while while loops repeat until a condition is no longer met.

For loops

6.1
7.4
5.9
8.2
6.8
0 6.1
1 7.4
2 5.9
3 8.2
4 6.8
0 6.1
1 7.4
2 5.9
3 8.2
4 6.8
2024-01-01 6.1
2024-01-02 7.4
2024-01-03 5.9
2024-01-04 8.2
2024-01-05 6.8
name Jungfraujoch
elevation_m 3571
readings_celsius [-2.3, -1.1, 0.4, 1.2, -0.8]
country Switzerland

While loops

Countdown: 3
Countdown: 2
Countdown: 1
warm day: 2024-01-02 7.4
warm day: 2024-01-04 8.2

Break and continue

Sometimes you need to interrupt a loop. The break statement exits a loop entirely, whereas continue skips the remainder of the current iteration and jumps to the next one.

Processing: 6.1
Processing: 7.4
Processing: 5.9
Found a hot day, stopping!
Hot day temperature: 8.2
Found None value in list.
Found None value in list.
Mean of present values: 6.27

Skipping missing values by hand like this is the idea behind the NaN-aware operations you will meet in the next subchapter: numpy marks a gap as nan and provides reductions such as np.nanmean that ignore it for you.

Control flowSyntaxWhat it does
if / elif / elseif cond: … elif cond: … else:Runs the first branch whose condition is True; else runs when none match.
forfor item in sequence:Repeats the body once for each item in a sequence.
whilewhile condition:Repeats the body as long as the condition stays True.
breakbreakLeaves the loop immediately.
continuecontinueSkips the rest of this iteration and moves to the next.
enumerate()for i, x in enumerate(seq):Pairs each item with its index, counting from 0.
zip()for a, b in zip(A, B):Walks two or more sequences together, stopping at the shortest.

1.2.3 Functions

A function names a reusable block of code. You define it with def, give it arguments, and return a value. A pure function depends only on its arguments and has no side effects, which makes it easy to test and reason about. Default arguments supply sensible fallbacks that callers can override by keyword.

6.0

A function can return more than one value by separating them with commas. Python packs them into a tuple, which the caller can unpack into separate names — the same unpacking you saw for coordinates earlier.

34.4 6.88
<class 'tuple'> (34.4, 6.88)
mild
warm

A function can also accept a variable number of positional arguments by prefixing a parameter name with *. Python packs everything the caller passes into a tuple under that name — useful when the number of values is not known in advance. The same * unpacks an existing sequence back into separate positional arguments at the call site.

6.47
6.88

When generated code lies: the shared default list

Ask an assistant for a function that collects the readings above a threshold and the version below is a common answer: a list parameter, defaulting to an empty list, filled in and returned. Called on one station it gives the right answer. Called on a second station it returns that station’s warm days with the first station’s still in front of them, and reports no error.

Station 1 warm days: [0.4, 1.2]
Station 2 warm days: [0.4, 1.2, 6.1, 7.4, 5.9, 8.2, 6.8]
Station 1 warm days: [0.4, 1.2]
Station 2 warm days: [6.1, 7.4, 5.9, 8.2, 6.8]

Summary

ConceptRule to remember
ListsOrdered and mutable; index from 0, and .append grows them.
TuplesImmutable records — safe to pass around, and they cannot be edited in place.
DictsMap keys to values; read safely with .get(key, default), walk pairs with .items().
Branchingif/elif/else runs at most one branch, and exactly one when including else.
Loopsfor walks a sequence, while repeats on a condition; break and continue steer them.
Pairingenumerate adds an index, zip walks two sequences together.
Functionsdef bundles logic with arguments, defaults, and a return value; *args collects extra positional arguments.
Default argumentsNever make a default mutable (out=[]): it is created once and shared across every call.

Resources