Programming with Python
Kühne Logistics University Hamburg - Fall 2026
The investor wants a numbers deck by Friday. A thousand orders sit in the system, one row each: minutes, price, zone.
Kevin’s plan is a 40-tab spreadsheet, one tab per zone, copied by hand. He looks at the pile, then at his list-of-lists, and says the only true thing he’ll say all week:
“We need a bigger boat than a list.”
Today we get the bigger boat: NumPy, one object that holds a thousand numbers and does arithmetic on all of them at once.
Three questions from Episode 6. Commit. Hands up before the reveal.
a) ceil(3.2) b) math.ceil(3.2) c) both
a) ceil(3.2) — from math import ceil binds only the name ceil. The module math itself was never imported, so math.ceil has nothing to reach through.
Kevin runs this exact script today and again tomorrow. Tomorrow’s numbers are…
a) different: random is random b) an error: seed 42 was already used c) the same three numbers
c) the same three numbers — every run starts from seed 42, so the stream replays from the top. That is the entire job of a seed: reproducible randomness. (Two batches inside one run would differ: the stream continues; a fresh run rewinds it.)
returns…
a) 2 b) 5 c) an error: the list is not sorted
b) 5 — median sorts the values internally before picking the middle one. You never have to sort first; 5 is the middle of 2, 5, 9.
A NumPy array holds many numbers under one name, like a list, but built for math. You make one from a list, then ask it about itself:
[12. 9. 15.]
(3,)
float64
3
np.array([...]) wraps a list; import numpy as np is the nickname everyone uses. .shape is (3,), .dtype is float64, .size is 3. One dtype for the whole array: every element shares the same type; that’s part of what makes it fast.
Here’s the bigger boat. The deck needs gross prices: 19% VAT on all three. With a list you loop; with an array you just multiply:
[14.28 10.71 17.85]
One operation lands on all elements at once: [14.28 10.71 17.85]. No loop, no .append, and on a thousand orders it’s also far faster.
Two builders make evenly-spaced arrays without typing every number, handy for axes and ranges:
[0 2 4 6 8]
[0. 0.25 0.5 0.75 1. ]
arange walks by a step and stops before the end, just like range. linspace splits a span into a fixed count of points, endpoints included.
Kevin multiplies a row of counts by two. What does this print?
a) [1, 2, 3, 1, 2, 3] b) [2, 4, 6] c) an error
Predict first. Commit to an answer before the next slide.
a) [1, 2, 3, 1, 2, 3] — that’s a plain list, and * 2 on a list repeats it. Wrap it in an array and the same * 2 does the math instead:
[1, 2, 3, 1, 2, 3]
[2 4 6]
Lists repeat; arrays compute. That’s why we’re here.
Open the exercise (scan the QR or type the link):
beyondsimulations.github.io/Introduction-to-Python/notebooks/ex_07_a/
First predict what happens, then run it.
Compare an array to a number and you don’t get one True/False. You get a whole array of them, one per element. That’s a mask, and you can filter with it:
[False True False True]
[41 33]
times > 30 is the mask; times[times > 30] reads the array through the mask and returns just the matching values. No loop, no if.
A mask answers two investor questions at once. .sum() counts the Trues (each counts as 1); .mean() gives the share that are True:
4
42.5
0.5
4 deliveries over 30 minutes, averaging 42.5, and late.mean() says half the run was late, one line each, straight into the deck.
What does calling .sum() on the mask give?
a) True b) 2 c) [False, True, True]
Predict first. Commit to an answer before the next slide.
b) 2 — .sum() adds the mask up, and each True is worth 1, each False 0. Two elements clear the bar, so the count is 2:
[False True True]
2
Summing a mask counts; averaging a mask shares. Same two tricks the lab asks for.
Open the exercise (scan the QR or type the link):
beyondsimulations.github.io/Introduction-to-Python/notebooks/ex_07_b/
First predict what happens, then run it.
Real data isn’t one row. Stack rows and you get a 2D array: here three days (rows) across four zones (columns: Nord, Sued, Hafen, Altstadt):
(3, 4)
11
.shape is now (3, 4): three days, four zones. One index picks the row, a second the column: deliveries[0, 2] is day 0, zone 2 (Hafen).
To sum a grid you must say which way to collapse it. The axis tells NumPy which direction disappears:
Nord Sued Hafen Altstadt
day0 [ 9 14 11 6 ]
day1 [ 15 12 8 9 ]
day2 [ 13 20 16 11 ]
axis=0 collapses DOWN the rows:
↓ ↓ ↓ ↓
37 46 35 26 one number per column (zone)
axis=1 collapses ACROSS the columns:
day0 → 40 · day1 → 44 · day2 → 60 one number per row (day)
[37 46 35 26]
[40 44 60]
axis=0 collapses DOWN the rows, one number per column (zone): [37 46 35 26]. axis=1 collapses across, one per day: [40 44 60].
The per-zone totals answer “how many?”, but the investor asks “which zone?”. argmax tells you WHERE the maximum sits, as an index:
1
max would give the value 46; argmax gives its position, 1. The busiest zone is Sued, sitting at index 1, not at the front. Position, not value: that’s the whole point of argmax.
The investor wants four numbers, one per zone. Which call?
a) week.sum(axis=1) b) week.sum() c) week.sum(axis=0)
Predict first. Commit to an answer before the next slide.
c) week.sum(axis=0) — four zones means four numbers, so the days must disappear: axis=0 collapses DOWN the rows, one number per column (zone):
[37 46 35 26]
b) would give three numbers (one per day); c) would give one number: the grand total, 144.
Open the exercise (scan the QR or type the link):
beyondsimulations.github.io/Introduction-to-Python/notebooks/ex_07_c/
First predict what happens, then run it.
Download your .py before you leave. Closing the tab without downloading loses your work.
np.array([...]) holds many numbers; arithmetic hits every element at once. No loop. Ask it .shape, .dtype, .size to know what you’re holding.arr > 30 is a True/False array: arr[mask] filters, .sum() counts the Trues, .mean() gives their share.axis=0 collapses DOWN the rows (one number per column), axis=1 across the columns (one per row); argmax tells you where the maximum sits.Next episode: the investor opens a data room, and Kevin lets an AI write his pandas. The arrays get column names, and a thousand orders become a table you can query.
NumPy has excellent free docs: the NumPy absolute beginner’s guide covers everything in this session and a little more.
For more, see the literature list of this course.
Lecture VII - NumPy for Scientific Computing | Dr. Tobias Vlćek | Home