Every practice problem asks you to write one function. This lesson covers how functions take values in, give a value back, and keep their own names separate from everyone else’s.
Defining a function
def gives a block of code a name. The names in brackets are the parameters: they receive the values passed in when the function is called.
def area(width, height):
return width * height
area(3, 4) # 12
Defining a function does not run it. The body runs only when the function is called, and it runs again on every call.
return is not print
return ends the function and hands a value back to the code that called it. print only shows text on the screen. The tests check what your function returns. A function that prints the right answer but returns nothing fails every test.
def double_wrong(x):
print(x * 2) # shows 10 on screen, then returns None
def double(x):
return x * 2 # gives 10 back to the caller
y = double_wrong(5) # y is None
y = double(5) # y is 10
A function with no return line, or with a bare return, gives back None. In a failing test, “got None” almost always means a missing return.
Local names and frames
Each call gets a fresh frame: a small box that holds that call’s parameters and the names it creates. These are called local names. Two functions can both use a name like a or s without any clash, because each name belongs to its own frame. The frame is removed when the call returns.
The frames of the calls in progress form a list called the call stack. A new call is added on top. The function on top is the one running, and every frame below it is waiting for an answer. Step through the figure and watch the stack grow and shrink.
def total(a):
s = 0
for x in a:
s += x
return s
def average(a):
return total(a) / len(a)
print(average([4, 8, 6]))
Lines 1 to 8 only define two functions. Defining a function stores it under its name. None of its lines run yet.
The call stack is worth learning now. RECR-2 uses it to explain recursion, which is a function that calls itself, and BIGO-4 uses it to count the memory that recursion needs.
Passing a list in
When you pass a list to a function, the parameter refers to the same list. No copy is made. So if the function changes the list, the caller sees the change:
def add_zero(a):
a.append(0)
trains = [5, 7]
add_zero(trains)
print(trains) # [5, 7, 0]
Passing a list costs almost nothing, even for a million values, because nothing is copied. Each practice problem says whether you may change the list you are given. If it does not say, return a new list and leave the input alone.
A mistake with default values
A parameter can have a default value, used when the caller leaves it out:
def greet(name, greeting="Hello"):
return greeting + ", " + name
greet("Asha") # 'Hello, Asha'
greet("Asha", "Namaste") # 'Namaste, Asha'
PYTH-3 counts as completed once you step through the figure to the last step.