Comp 112
Lecture 2
Calling and Defining Functions2018.02.06
In Python, a function (“procedure”, “subroutine”) is like a program within a program.
To call (“invoke”) a function, write its name followed by a parentheses-enclosed and comma-separated list of arguments:
Calling a function:
runs some code, potentially causing effects (like a statement),
returns a value (like an expression).
So functions generalize both statements and expressions.
From now on “statement” means “statement or function call” and “expression” means “expression or function call”.
We already met two functions last week:
The print
function takes an argument and has the effect of printing its value to the screen.
We may also want to take input from the user (keyboard) and give it to the program.
The input
function does this:
The prompt is a string that gets print
ed to let the user know what to enter:
We can store the result in a variable and use it later in the program:
Instead of storing the value returned by a function in a variable:
We can instead use it directly in an argument to another function:
This is called function composition: using the output (i.e. return value) of one function in an input (i.e. argument) to another.
Python includes some basic coercion functions that convert values from one type to another.
These are named after the target type:
str (<expression>) # tries to convert the argument to a string
int (<expression>) # tries to convert the argument to an integer
float (<expression>) # tries to convert the argument to a float
bool (<expression>) # tries to convert the argument to a boolean
What they do depends on the argument’s type (see reading for details).
Some conversions are not defined and result in an error.
Others may be counterintuitive, so check how they work before using them.
Soon we will learn how to write our own conversion functions that do whatever we want.
If an expression has a type different from the one expected, Python may silently try to convert it using a coercion function.
This is called implicit coercion.
Example: the print
function expects a string
argument, if it finds something else then it silently calls str
on it.
gets automatically converted into
Implicit coercion may seem convenient but is usually bad, especially when combined with overloading.
What will the following do?
def my_fun (x , y) : # the function header
print ("i'll add " + str (x) + ' and ' + str (y) + ' for you...') # a statement in the function body
return x + y # a return statement in the function body
Function definitions have two parts:
A header consisting of:
def
” – signals the start of a function definition,:
” that signals the end of the function header.A body consisting of:
The local variables of a function are its parameters and any variables defined in its body.
The scope (i.e. region of validity) of a local variable is only the function body.
Local variables act like “scratch paper” for a function: when the function call is over, they disappear.
In contrast, global variables are variables defined outside of any function.
They may be looked up but not assigned from within a function.*
Trying to assign a global variable from within a function instead creates a local variable with the same name.
Local variables shadow global variables with the same name.
Global variables should be used sparingly: when a function depends on a value, it should generally be passed in as an argument.
Global variables are for program-wide parameters that would be tedious to pass to all functions:
A return statement aborts the execution of statements within a function body.
The value of the expression following the keyword “return
” is returned to the function’s caller.
If return
is not followed by an expression, then “None
” is assumed.
If the function body ends without a return
statement, then “return None
” is assumed.
In Python there is a type with exactly one value.
The type is called “NoneType
” and its only value is called “None
”.
The None
value provides no information, so the Python interactive interpreter suppresses printing it.
It is important to understand the difference between return
ing and print
ing a value.
A value that is return
ed from a function is available for further use within the program.
It can be assigned to a variable, used in an expression, or passed as an argument to another function.
But a value that is print
ed to the screen is lost to the program: it can no longer be examined or manipulated.
In fact, print
is a function that always returns None
:
Compare:
All functions take input through their arguments and give output through their return values.
Some functions also interact with their environment through effects (e.g. print
and input
).
Functions that do so are called effectful.
In order to communicate with the outside world a program must be effectful.
But you should structure your programs so that as many functions as possible are effect-free.
It’s much more flexible to return
a value than to print
it.
A function call creates a detour in the flow of program execution:
return
statement is reached.†return
is evaluated.‡†) If no return
is encountered, then “return None
” is implied.
‡) If no expression follows return
, then “return None
” is implied.
def add_and_greet (x , y) :
it = x + y
greet_user ()
return it
def greet_user () :
it = print ('hi there!')
x = 39
y = add_and_greet (1 + 2 , x)
Lets see what this program does by drawing its call graph.
For a function to work properly, its arguments must fulfill certain preconditions.
Most important among these are their types.
For a function to be useful, its returned value must fulfill certain postconditions.
Most important among these is its type.
Dynamic languages like Python don’t keep track of these things, but you should using documentation string comments:
def quotient (x , y) :
"""
signature: int , int -> int
precondition: y != 0
description: returns the quotient of its arguments
"""
return x // y
A function signature describes the expected input and output types.
A precondition is a boolean expression, or “predicate”, about the function arguments that should evaluate to True
.
You should document every function with a signature, any preconditions and a brief description.
Reading:
Come to lab on Thursday.
Complete homework 2.