Programming Fundamentals

Functions

↩ Back
01

Defining and Calling

Reference
Writing a Function

A definition tells Python what the function does and nothing more. The body sits there unused until a call arrives, and only then does it run.

def greet(name): print("hello", name) greet("ana") # hello ana greet("bo") # hello bo
Four parts to write in order
defThe keyword that opens a definition. It is followed by the name you choose for the function.
The nameWritten in lower case, usually a verb, and reusable anywhere below the definition. greet says what the call will do.
The bracketsThey hold the parameters. An empty pair means the function needs no values from outside.
The bodyEvery indented line under the colon belongs to the function. The first line back at the left margin is outside it again.
Interactive
Where the Program Goes

Press run and watch the highlight. Line 1 is read and stored, never executed. When the call on line 4 arrives, control jumps up into the body, and once the body ends it comes back to the line below the call.

def greet(name): print("hello", name)print("start")greet("ana")print("end")
the highlight travels up and then back down
Output
press run to execute
Definition first, call second

Python reads the file from top to bottom. Calling greet before its definition raises NameError, because at that moment the name still means nothing.

Detail
Why Functions Earn Their Place
1
One copy. You avoid pasting the same code multiple times. The instructions live in a single spot, so a correction there fixes every call at once.
2
A readable name. total = average(scores) says what happens. Six lines of arithmetic in the same position say how it happens, which is a question for later.
3
A closed box. Names created inside the function stay inside. The rest of the program cannot disturb them and they cannot disturb the rest of the program.
4
Testing. A function with parameters and a return value can be checked on its own: hand it values, compare what comes back with what you expected.
02

Parameters and Arguments

Reference
Parameters vs Arguments

A parameter is the name written between the brackets of the definition. An argument is the value handed over in the call. During the call the parameter holds that value, and when the call ends the parameter disappears.

def repeat(word, times): # word and times are parameters print(word * times) repeat("ha", 3) # "ha" and 3 are arguments repeat(times=2, word="ok") # same idea, names written out
Every way to hand values over
FormMeaningExampleBinding
f(a, b)positional, matched by orderrepeat("ha", 3)word='ha', times=3
f(x=a, y=b)keyword, matched by namerepeat(word="ha", times=3)word='ha', times=3
f(y=b, x=a)keyword in any orderrepeat(times=3, word="ha")word='ha', times=3
f(a, y=b)positional first, then keywordrepeat("ha", times=3)word='ha', times=3
Two rules Python will not bend

The count has to match: two parameters need two arguments, and a call with one or three raises TypeError. And once a keyword argument appears, every argument after it needs a keyword too, so repeat(word="ha", 3) is a syntax error.

Interactive
Build the Call

Same definition, your choice of values and your choice of form. Watch the binding panel: all three forms fill the parameters with exactly the same values.

def order(item, amount): print(amount, "x", item)
The call you built
order("tea", 2)
Inside the call
Output
Reference
Default Arguments

A default is a value written into the definition. The call may leave that argument out and the default fills the gap, so one function covers the common case and the unusual one.

def tag(amount, currency="EUR", discount=0): return str(amount - discount) + " " + currency print(tag(40)) # 40 EUR print(tag(40, "USD")) # 40 USD print(tag(40, discount=5)) # 35 EUR
Check the arguments to include in the call
amount is always given
tag(40)
Output
Highlighted values arrive from the call. Faded values fall back on the defaults written in the definition.

Defaults go last

A parameter with a default cannot sit before one without, so def tag(currency="EUR", amount) raises a syntax error. Python matches positional arguments by order, and a gap in the middle of that order cannot be filled.

03

Return

Reference
Handing a Value Back

Return ends the call and sends one value to the place that asked for it. The call itself becomes that value, so it can be stored, printed or used in a larger expression.

def area(width, height): return width * height a = area(3, 4) # a is 12 print(area(2, 5) + 1) # 11 total = area(3, 4) + area(2, 5) # 22
What return does and does not do
It ends the callNothing written after the return line runs. The function stops there and control goes back to the caller.
It carries a valueThe value takes the place of the call in the expression, which is why area(3, 4) + 1 is arithmetic on 12.
No return, still a valueA function without a return statement ends when its body ends, and the value that reaches the caller is None.
It shows nothingReturn writes nothing on screen. If you want to see the value you have to print it, either inside or outside the function.
print shows a value to the reader · return hands it to the program
Interactive
print or return

The two definitions differ in one word. Run both and compare the second printed line: the function on the left shows the sum and hands back nothing, the one on the right hands back the sum and shows nothing.

A function that prints
A function that returns
def add(a, b): print(a + b)r = add(2, 3)print(r)
def add(a, b): return a + br = add(2, 3)print(r)
Output
press run to execute
Output
press run to execute
A printed value is gone once it reaches the screen. A returned value stays in the program and can be used again.
Detail
Multiple Return Points

A function may hold more than one return line. The first one reached wins, and the rest of the body is skipped, which removes the need for a long chain of else branches.

def grade(mark): if mark < 5: return "fail" if mark < 7: return "pass" return "distinction" print(grade(4)) # fail print(grade(6)) # pass

Return carries one value, and a tuple is one value holding several. Writing the values with commas builds that tuple, and unpacking it on the other side gives them separate names again.

def stats(numbers): return min(numbers), max(numbers) low, high = stats([4, 9, 2]) print(low, high) # 2 9
Unpacking on the left of the equals sign is the same move used with tuples in the previous guide.
04

Variable Scope

Reference
Local Names

The scope of a name is the region of the program where that name can be used. A name created inside a function is local: it appears when the call starts, it lives as long as the call lasts, and it is gone the moment the call ends.

def shout(text): loud = text.upper() # loud is local to this call return loud print(shout("hey")) # HEY print(loud) # NameError: name 'loud' is not defined
Which names are local
ParametersEvery parameter is a local name. text exists only while the call runs, whatever the argument was called outside.
AssignmentsAny name given a value inside the body is local, including a name that also exists outside.
Global namesA name created at the left margin, outside every function, is global and can be read from anywhere below it.
what happens inside a call, stays inside a call
Interactive
Global Frame vs Call Frame

Press step and follow the two panels below. The global frame holds the names of the program, the call frame appears when the call starts and vanishes when it ends. The last line asks for a name that no longer exists.

total = 0def add_fee(price): fee = price * 0.2 return price + feetotal = add_fee(100)print(total)print(fee)
step 0 of 8
Global frame
empty
Call frame
no call running
Press step to start.
Output
press step to execute
Detail
Reading vs Writing Globals

A function can read a global name without any ceremony. Assigning to that name is a different matter: the assignment creates a local name of its own, and the global one is left untouched.

Reading works
Writing stays inside
rate = 0.2 def fee(price): return price * rate print(fee(100)) # 20.0
rate = 0.2 def reset(): rate = 0 # a new local name reset() print(rate) # 0.2, unchanged
Questionlocal nameglobal name
Created byA parameter or an assignment inside a functionAn assignment at the left margin
Lives forThe length of one callThe length of the program
Read from inside a functionYes, its own functionYes
Written from inside a functionYesNo, the assignment builds a local name instead
Two calls at onceOne separate copy per callOne copy, shared

Python does offer the global keyword, which forces an assignment to reach the global name. Reserve it for rare cases: a function that edits names behind your back is hard to read and harder to correct.

Send values in through parameters, send results out through return. That pair covers almost everything you need.
05

Check Yourself

Question
What Does This Print?
The code
def double(n): n = n * 2 x = 5 double(x) print(x)
Pick one.
Challenge
Predict Four Outputs

Trace each fragment before pressing Check. The answer button is there for when your trace and the verdict disagree.

type the printed values separated by spaces · quotes and brackets are ignored
1A function with no return
def add(a, b): print(a + b) r = add(2, 3) print(r)
2With and without the default
def power(base, exp=2): return base ** exp print(power(3)) print(power(2, 3))
3Which return is reached
def check(n): if n > 10: return "big" return "small" print(check(10))
4An assignment inside a call
count = 3 def bump(): count = 10 bump() print(count)
06

Summary

Recap
What You Can Do Now
1
Write a definition with def, indent its body, call it from below, and say where control travels on each line.
2
Tell a parameter from an argument, and pass values by position, by keyword or by both in the order Python accepts.
3
Give a parameter a default, leave that argument out of the call, and explain why parameters with defaults are written last.
4
Use return to hand a value back, predict when None arrives instead, and say how return differs from print.
5
Leave a function early with a second return, and send several values back as a tuple ready for unpacking.
6
Decide whether a name is local or global, and predict which assignments reach the outside of a call and which do not.