Define
A function is a named group of steps you can run whenever you need them. def average(nums): makes one and stores it under the name average. The indented lines 2 and 3 are its body: they do not run yet.
First call
Line 5 calls average with the list [8, 6, 10]: the argument. Python pauses line 5 and jumps into the function. A call frame appears, scratch space for this one call, and the parameter nums now names the list.
Now the body runs, top to bottom. Line 2 adds up the list with the built-in sum(): 8 + 6 + 10 is 24. total = 24 is a local variable: it lives only in this call's frame.
Line 3 works out total / len(nums): 24 / 3 is 8.0, because / always gives a float. return ends the call and sends 8.0 back to line 5, where the call was made. The frame is cleared away.
Line 5 carries on where it paused. average([8, 6, 10]) has become the value 8.0, so a = 8.0. The local names nums and total are gone: using total out here stops with a NameError.
Second call
Line 6 calls average again, with [4, 5]. A brand-new frame appears: nums = [4, 5], and line 2 runs again, so total = 9. Nothing is left over from the first call.
Line 3 runs again: 9 / 2 is 4.5. return hands 4.5 back to line 6, which stores it: b = 4.5. This frame is cleared too. One definition, two calls, two answers.
Use and pitfalls
Line 7 calls print(), a function Python already provides. You call it the same way: its name, then the arguments in brackets. It writes a and b with one space between them: 8.0 4.5.
Delete the word return and line 3 still works out the average, then throws it away. A function that ends without return sends back None, Python's value for "nothing". Now a and b are None.
Try it yourself
;; step 1/9 · line 1: def average(nums): >>> def average(nums): ... total = sum(nums) ... return total / len(nums) ... >>> average # just the name: nothing runs <function average at 0x…>
The tray is a call frame: each call gets a fresh table for its local names (here nums and total). When the call returns, the frame is released and those names can no longer be reached from outside. The / operator always gives a float, even when the division is exact: 24 / 3 is 8.0, not 8. Use // for whole-number (floor) division.