How to Define and Call Functions in Python
Python is a powerful programming language that can solve many problems for the data professional, e.g., connect to a database, run data transformations and preprocessing, integrate with Power BI and many others. In all use-cases you should avoid repetition while maintaining a good structure and encapsulating different pieces of the program logic into self-contained units of code. In this Python tutorial, we will look at how to do this using functions.
Python functions help you encapsulate blocks of code in a single entity that performs one single operation. These handy constructs allow you to solve a certain problem once and then reuse this solution in other parts of your python program. This process can happen with or without parameters that you pass to your function. In this tutorial, we introduce Python functions. Let us start with what is function and how to define and call a function.
What is a function?
A function is a reusable set of instructions. The instructions consist of your code that should solve and pertain to only one problem. You can reuse a function as many times as needed in your program. I firmly believe grasping functions and how they work will be a valuable steppingstone in your Python journey.
Define and call a Python function
To use a function, you must define it first. Every function consists of:
- The keyword
def. Use it to define your function.
- A function name. Define according to what the function does. Therefore, the name should contain a verb and a subject, i.e., what are we doing with something.
- One or many function parameters following the function name inside parenthesis. We can also have a function with no parameters as in the example below.
- Colon. Use it to signify the end of the function name and the beginning of the definition of the function body.
- Function body. Here we provide the code of the function. In this case we just print out 'Hello World'. You have two types of functions according to what they return: returning functions and void functions.
First, "returning" functions: they contain a
return statement and return one or many values:
Second, void functions: they perform an action, but do not return anything as shown with this Python code:
Defining a function with parameters is easy with this syntax:
In the parenthesis after
def, we provide a list
of one or many parameters. We do not need to provide a data type explicitly; Python
will determine it dynamically. Here are the important points to keep in mind:
The parameters you defined become mandatory. If you want to invoke your function without passing an argument to either of your parameters, the function call will fail:
The order of passing arguments matters, unless you don't provide arguments in a specific order of choice:
That's why doing this call fails:
You can define default values for your parameters:
Here we pass
0 as a default value to
When we call the function without passing an argument for
experience, the default value will be used. This is essentially how you make
the parameter optional:
In certain cases, you need isolated units of code that do not accept parameters but still do a helpful bit of work in your program or data analysis script. For example:
Notice how calling the function returns a datetime object:
What you could do (unless that is what you need), is assign the function return value to a variable and print that variable out:
Assigning the function return result to a variable is an accepted way to work with the output of a function.
Along with the functions that return a result, we already saw a couple of examples
of void functions which do not return a result, for example the ones above that
print() command. Using
print() in a void function is handy if you want
to provide feedback in your script. What if you wanted to log some activity, for
example when a user accessed something and from where?
We can have a void function that does not give any feedback, for example:
We just form a tuple of the input parameters and append this tuple to the global
users_and_times. Calling the function gives
But the information has been successfully stored:
Nesting one or more functions under another is allowed in Python. In certain scenarios the reusability of your code benefits from nesting. Let's take the following example:
Our inner function is
check_nr() and outputs
on the number supplied as argument. The outer function is
get_result(), which perform an action on the single parameters it accepts.
The action (raise to the power of 2 if even or to the power of 3 if odd) depends
on the outcome of the inner function. On purpose here I have used one and same name
for the parameter
number. While legal, using similar
names for parameters may hurt readability or create confusion.
Nesting functions can obviously be a two-sided knife. Beware of nesting on too many levels. It is better to rest a couple of functions under an outer function than nesting a couple of functions under each other creating several nested levels. Keep in mind though you can declare the nested function(s) at the time of declaring the outer function, unlike what we just saw. For example:
Notice how the nested function has access to the variables contained in the enclosing
function. Here the
check_nr() function is local and
cannot be used outside of the enclosing scope. Try calling
check_nr() from this example separately and you will
get an error.
Whether we are talking about nested functions or functions in general we must mention the scope rules Python has and you as the programmer must keep in mind. There are two aspects:
- variables defined in a function (inside a
defstatement) are local. Those are variable that are available only inside this function and are unavailable to other pieces of the code outside of the function.
- Variables defined outside of function are global. Those variables we can use in our namespace defined by the current module (usually that is the script file that you are currently writing).
It is allowed to have variables that have identical names but different scopes:
In the example above we have the variable
which "lives" inside the
function. I have commented out the return statement of the function so that the
output is only the variable's address in memory. Additionally, we have the
factor which has a different location
in memory as you can see on the example above.
As the next and final point, we must mention
functions. These are anonymous functions that can be created inline. They do not
need a function name that we invoke later; instead, a
expression returns the function itself. The general expression for creating a lambda
lambda arg1, arg2, …, argN: expression using the arguments provided
Here are two examples:
The first example has only one argument, while the second example accepts three arguments. Let us look at two behaviors that lambda functions allow:
1 - Using a
lambda inside a
def. In the
Nested functions section above, we
examined a simple function that checks if a number is odd or even. The same
can be accomplished with a lambda and a ternary check:
You must not forget to assign the enclosing function to a variable as this serves
as a call to the lambda, which returns a function. Only then can you pass an argument
to it. I have illustrated this on the example above by checking the type of the
2 - Using a
def inside a
Here we use the output of a previously defined function as part of the expression we pass to the lambda.
In this tutorial, we examined defining and calling functions, nesting functions, variable scope, and lambda functions. We have not discussed some advanced function topics such as recursion, certain function perks as well as a bit more on functional programming as it relates to lambdas. Nevertheless, this tutorial should serve as your primer to Python functions and their core functionality.
"Learning Python" 4th edition, by Mark Lutz, published by O'Reilly 2009, chapters 16 and 19.
About the author
View all my tips
Article Last Updated: 2022-02-24