How to Define and Call Functions in Python

By:   |   Updated: 2022-02-24   |   Comments   |   Related: More > Python


   Free MSSQLTips webinar - "Efficient Monitoring and Management of SQL Server" (click to register)

Problem

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.

Solution

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:

print hello returning function

Second, void functions: they perform an action, but do not return anything as shown with this Python code:

print hello void function

With parameters

Defining a function with parameters is easy with this syntax:

function with parameters

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:

function call fail with no arguments for defined parameters

The order of passing arguments matters, unless you don't provide arguments in a specific order of choice:

function arguments

That's why doing this call fails:

function call fail because of wrong argument order

You can define default values for your parameters:

example function definition with a default value for a parameter

Here we pass 0 as a default value to experience. 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:

example calling a function with a default value for a parameter

Without parameters

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:

function definition without parameters

Notice how calling the function returns a datetime object:

function call  without parameters

What you could do (unless that is what you need), is assign the function return value to a variable and print that variable out:

assign a function call to a variable

Assigning the function return result to a variable is an accepted way to work with the output of a function.

Void functions

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 had the 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:

void function definition

We just form a tuple of the input parameters and append this tuple to the global variable users_and_times. Calling the function gives no output:

calling a void function

But the information has been successfully stored:

check the global variable after calling a void function

Nested functions

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:

nesting function by using two separate function definitions

Our inner function is check_nr() and outputs even or odd depending 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:

nesting function by using one definition

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.

Scope

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 def statement) 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:

same variable names for a variable inside and outside of a function

In the example above we have the variable factor which "lives" inside the get_result() 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 global variable factor which has a different location in memory as you can see on the example above.

Lambda Functions

As the next and final point, we must mention lambda functions. These are anonymous functions that can be created inline. They do not need a function name that we invoke later; instead, a lambda expression returns the function itself. The general expression for creating a lambda function is:

lambda arg1, arg2, …, argN: expression using the arguments provided 

Here are two examples:

example of lambda functions with one and many arguments

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:

nested lambda function with ternary operator

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 result variable.

2 - Using a def inside a lambda:

nested function in a lambda expression

Here we use the output of a previously defined function as part of the expression we pass to the lambda.

Conclusion

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.

Reference

"Learning Python" 4th edition, by Mark Lutz, published by O'Reilly 2009, chapters 16 and 19.

Next Steps



Get Started Now - Click here to get your free 14 day trial of SolarWinds Database Insights




get scripts

next tip button



About the author
MSSQLTips author Hristo Hristov Hristo Hristov is a Microsoft certified data professional, specializing in Power Apps and Power BI.

View all my tips


Article Last Updated: 2022-02-24

Comments For This Article





download














get free sql tips
agree to terms