def printArgs(a, b, c=17, d=4.3):
print("a is: "+str(a))
print("b is: "+str(b))
print("c is: "+str(c))
print("d is: "+str(d))
Functions
Functions
A function provides a convenient way to âwrap upâ code to accomplish a particular task. Once a function is written, it can (generally) be used without us needing to know anything about how it works. This is a very powerful concept, and complex programs are often made by chaining many functions together.
In general, a function has a well-defined set of inputs (sometimes known as the functionâs âargumentsâ) and outputs (sometimes called the âreturn valueâ). In Python, and most other modern programming languages, a âfunction callâ looks like
= function_name(input1, input2, input3) output1, output2
We have already encountered a couple of functions: we have used print()
and type()
. These are known as âbuilt-in functionsâ, as they are a core piece of the Python programming language. For a full list of built-ins, see this page of the official Python documentation. Other functions can be accessed by âimportingâ them from âmodulesâ - we will learn more about this later.
It is easy to write your own functions. This is done by using the def
command, and writing something like:
def function_name(input1, input2, input3):
[code to compute outputs...]return output1,output2
Note that function_name
, input1
, output1
etc can be any name you wish to use. In general, a function definition comprises: - The keyword def
, followed by - The function name, followed by - An opening parenthesis (
, followed by - Zero or more input variables, followed by - A closing parenthesis )
, followed by - A colon, :
This is all followed by an indented block of code containing zero or more lines of the form - The keyword return
, followed by - Zero or more variable names (or valid expressions)
For example
def addThreeNumbers(first, second, third):
return first + second + third
We can then âcallâ this function:
= 3
a = 5
b = addThreeNumbers(a, b, -1) result
The variable result
should now contain the value 7
(= 3 + 5 - 1).
A few things to notice from this example: - When we âcallâ (use) a function, we can give it both named variables (a
and b
), and values (-1
). - The variable names we pass to the function donât need to match the variable names used when âdeclaringâ (defining) the function - so we can use a
and b
instead of first
and second
. - The return
keyword specifies what the function result will be.
Hereâs a slightly more complicated example, which calculates the sign and absolute value of the input (unless it is zero):
def signAndValue(x):
if x == 0:
print("Unable to handle zero")
elif x > 0:
return +1, x
else:
return -1, -x
print("Hope that helps !")
Function arguments
The following function calculates the sum of the integers from n0
to N
, inclusive: \(\sum_{n=n_0}^N n\).
def sumIntegers(N, n0):
= 0
result for i in range(n0, N+1):
+= i
result return result
Note that the function definition has the upper-limit, N
, as the first input argument, contrary to what one might expect - the reason for this will soon become clear.
It might usually be the case that we want to start our sum at \(n_0 = 1\). Python allows us to provide this as a âdefaultâ value for the n0
variable, by simply changing the function declaration:
def sumIntegers(N, n0=1):
= 0
result for i in range(n0, N+1):
+= i
result return result
Now, if we call sumIntegers
with only one argument, it is assumed that this is N
, and n0
receives its default value. However, if we provide two arguments, these are interpreted as N
and n0
respectively.
We can have multiple arguments with default values. For example, we can extend our function to compute \(\sum_{n=n_0}^N n^{\,p}\) for some power \(p\):
def sumIntegers(N, n0=1, p=1):
= 0
result for i in range(n0, N+1):
+= i**p
result return result
If we call this specifying one, two, or three arguments, they are assumed to occur in the same order as in the function declaration (i.e. N
, n0
, p
). However, we can also explicitly specify which arguments we wish to set. For example
= sumIntegers(10, p=2) result
would calculate the sum of squares, leaving n0
set to its default value.
If inputs are not labelled, they are assumed to be provided in the same order as in the function definition. The following function displays the value of each argument: you can use it to check you understand the different ways to call a function.
def printArgs(a, b, c=17, d=4.3):
print("a is: "+str(a))
print("b is: "+str(b))
print("c is: "+str(c))
print("d is: "+str(d))
Note that the printArgs()
function above does not contain an explicit return
statement. It is an example of a function that has âside-effectsâ: it does something that isnât apparent from knowledge of its outputs. Sometimes, it is necessary to write code with side-effects, especially for data input or output. However, they are a common source of problems, and they should be avoided where possible.
Scope of variables in functions
When you pass a variable to a function, you effectively create a copy of the information it contains (unless it is a âlistâ or âarrayâ - more on those in a later exercise!). Changing the variable within the function does not change the value outside the function, unless you pass it back via an output. For example:
def increment(x):
+= 1
x print("Inside increment, x is now "+str(x))
return x
= 0
x
# Notice that we don't do anything with the return value here
increment(x) print(x) # x will therefore still be zero
= increment(x) # This time we are updating the value of x
x print(x) # x will be one.
There is a way to access external (global
) variables from within functions. They might be used in this situation:
= False
system_is_setup
def setup():
global system_is_setup
if system_is_setup == False:
# Do system setup tasks
...else:
# check system is ok
...
return
Generally speaking, functions using global
variables in this way is a poor choice of implementation because some hidden code is modifying the global state without us, as users, being in control or even aware. We do often define variables of this nature when we use python objects that have a special internal (private) state. We will learn about this later.
Function documentation
To allow anyone to use your function without knowing the details, you need to document it. This appears in the code just after the definition of the function (and other python entities too). This step may seem unimportant at first, but is critical for re-using your code and distributing it to other people ! Another way is to just call help(<functionname>)
and it will output the documentation.
help(print)
Help on built-in function print in module builtins:
print(\*args, sep=' ', end='\n', file=None, flush=False)
Prints the values to a stream, or to sys.stdout by default.
sep
string inserted between values, default a space.
end
string appended after the last value, default a newline.
file
a file-like object (stream); defaults to the current sys.stdout.
flush
whether to forcibly flush the stream.
Documentation is provided by writing âdocstringsâ at the start of any function you create. These consist of blocks of text enclosed in triple inverted commas:
"""[Documentation goes here...]"""
In scientific Python, docstrings usually follow a certain style, e.g.:
def increment(x):
"""increment x.
Parameters
----------
x : integer
the number you want to increament
Returns
-------
x : integer
incremented x
"""
+= 1
x print("Inside increment, x is now "+str(x))
return x