A function (sometimes referred to as a method or procedure) is a set of statements designed to perform a particular task.
Python functions are usually referenced by a name, and when this is the case, the set of statements can be reused or executed as many times as needed in a program. It is a way to run the same statements from multiple places in a program without having to rewrite them each time they are needed.
In Python, functions are first-class citizens. This means that you can pass functions around like any other object, assign them to variables, store them in lists and tuples, or define them inside other functions.
Python already comes with pre-defined functions like print()
. These predefined functions are known as built-in
functions, and Python allows you to create your functions called user-defined
functions.
This article addresses the following touchpoints:
- How to define functions in Python
- Function parameters and arguments
- Return values
- How to call Python functions
- Python Lambda functions
- Variable scope
If you've not set up Python locally and would like to run the examples used in this article, you can use an online interpreter like OnlineGDB Python Interpreter.
How to define functions in Python
A way to define a function in Python is by using the def
keyword. Let's write a function that accepts two numbers and returns their sum as a new value:
# editor
def sum(value1, value2):
"""This sums two values"""
sum_of_values = value1 + value2
return sum_of_values
From our above function:
- The function name is provided right after the
def
keyword. - The parenthesis holds the' function parameters' right after the function name.
- The code block indented from the next line (after the colon) is the
function body
. - The first statement in the function body is the function's documentation string (
docstring
) and is optional. - The
return
statement is used to end the execution of a function while returning a specified value.
Function parameters and function call
Function parameters
are names used to represent real values that are provided when a function is called. Let's define a function call
as a request to execute our function. To call our function, we only need to write its name followed by a parenthesis. We'll assign our function call to a variable in our next block. This means that the value of our variable will be equal to our function's return value:
# editor
result = sum()
print(result)
Our above code will return:
TypeError: sum() missing 2 required positional arguments: 'value1' and 'value2'
Remember that in our function definition, we used two parameters, value1
and value2
, to represent the real values to be summed.
To provide the values that we want to be summed, we'll place them right inside the parenthesis
in our function call. The values we provide during our function call are called `function arguments.
# editor
result = sum(5, 6)
print(result)
# console
11
Our function can return different outputs based on predefined conditions in its definition. For instance, if we would like to work with only small numbers, we can choose to return a different output if both numbers, when summed, would be greater than 100
:
# editor
def sum(value1, value2):
sum_of_values = value1 + value2
if (sum_of_values > 100):
return "Too big!"
return sum_of_values
result = sum(90, 32)
print(result)
# console
Too big!
During a function definition, the names that represent the values we intend to supply to the function are called `function parameters.
The actual values provided to the function during a function call are called `function arguments.
The return statement
- The return statement is used to end the execution of a function while returning a specified value.
Its default value would be' None' without using the return
keyword to tell our function what to return. Let's test this by creating a function without a return
statement and then calling it:
# editor
def sum(value1, value2):
sum_of_values = value1 + value2
print(sum(5, 9))
# console
None
The function also returns None
by default when the return
keyword is provided without a value. This makes it an empty return
:
# editor
def sum(value1, value2):
sum_of_values = value1 + value2
return
print(sum(5, 9))
# console
None
Positional arguments
By default, function arguments in Python are `positional arguments. This means that the values have to be ordered the same way they were supplied during the function definition:
# editor
def sum(value1, value2):
print("This is value2: " + str(value2))
print("This is value1: " + str(value1))
print(sum(90, 32))
# console
This is a value2: 32
This is a value1: 90
None
Keyword arguments
Keyword
arguments are an alternative to positional
arguments. When we use keyword arguments in a function call, Python determines what parameter it represents through the parameter name
used in the function definition. In this way, we can place our arguments out of order:
# editor
def sum(value1, value2):
print("This is value2: " + str(value2))
print("This is value1: " + str(value1))
print(sum(value2 = 32, value1=90))
# console
This is a value2: 32
This is a value1: 90
None
Required arguments
As we saw earlier, the arguments are required by default. This means that Python will throw an error if the number of parameters provided in the function definition
is not the same as the number of arguments supplied in the function call
:
# editor
def sum(value1, value2):
sum_of_values = value1 + value2
return sum_of_values
result = sum(90)
print(result)
# console
TypeError: sum() missing 1 required positional argument: 'value2'
Default arguments
To make an argument
optional in a function call, we have to give it a default value in our function definition. This default value will be used if no argument for that parameter
is supplied during the function call
:
# editor
def sum(value1, value2=10):
sum_of_values = value1 + value2
return sum_of_valueshis
result = sum(90)
print(result)
# console
100
Arbitrary Arguments
When the exact number of arguments
to be supplied during our function call is not known, we can use arbitrary arguments. We add an asterisk (
*) to use arbitrary arguments before the parameter name in our function definition. This will make the parameter a
tupleand our function will receive a tuple of arguments for every argument supplied in place of the parameter during our
function call`:
# editor
def sum_all(*values):
print("A tuple of all the arguments:", values)
sum_of_all_values = sum(values)
return sum_of_all_values
result = sum_all(4, 7, 13, 45)
print("The sum of all supplied arguments:", result)
# console
A tuple of all the arguments: (4, 7, 13, 45)
The sum of all supplied arguments: 69
Python Lambda functions
Another way to define functions in Python is by using the lambda
keyword. This method of function-definition is mostly used to create anonymous functions
, functions that have no name, hence the word anonymous
.
By syntax, lambda functions
can have multiple arguments but are restricted to only one expression
. Let's redefine our sum()
function using the lambda
keyword:
lambda value1, value2: value1 + value2
A few things to note:
- Our function definition does not have a
return
statement. The expression after the column (:
) is by default, the return value. - There is no way to reuse our function since it can't be referenced by a name.
You'll find Lambda functions useful when you need to pass a function as an argument to higher-order functions
. Higher-order functions are functions that operate on other functions, either by taking a function as its argument or returning a function. The map()
is an example of a higher-order function.
In Python, the map function takes a function and a list as arguments. This is one case where we don't need our function to be reusable, hence, the need for a lambda function
. Let's use the map()
and lambda
functions to return half of every number in a list:
# editor
list_of_numbers = [19, 12, 45, 72, 10]
halved_list = list(map(lambda value: value/2 , list_of_numbers))
print(halved_list)
# console
halved list: [9.5, 6.0, 22.5, 36.0, 5.0]
To be able to reuse a lambda function, we can assign it to a variable:
# editor
sum = lambda value1, value2: value1 + value2
result = sum(7, 9)
print(result)
# console
16
Variable scope
Variables that are defined inside a function body
are locally scoped. This means that they can only be accessed inside the function definition:
# editor
def example_function():
word = "inevitable" # the word variable is locally scoped
return word
print(word)
# console
NameError: name 'word' is not defined
Notice that our print()
statement is outside our function-defintion. As this is outside the scope of our function body
, the word
variable is not accessible to statements or expressions that are outside our function definition.
To make our word
variable accessible to every statement and expression in our code, we have to declare it outside the function definition. In this way, it is globally scoped:
# editor
word = "inevitable" # the word variable is globally scoped
def example_function():
return word
print(word)
# console
inevitable
Important things to note
When defining a function using the def keyword, after the function name and colon, the function-body should be indented from the next line.
Notice how we indented our function body in def
function definitions. This is a way to tell Python that everything we are about to write next belongs to our function definition. If your function body is not indented, Python will assume that you've begun a different statement:
# editor
def sum(value1, value2):
sum_of_values = value1 + value2
return sum_of_values
result = sum(3, 7)
print(result)
# console
IndentationError: expected an indented block
A function name should be descriptive, straight to the point and timeless.
Notice how we named our first function sum
. This is because its job is to sum values. Doing this would help anyone know what our function does by just looking at its name.
Function naming is a very important part of function definition and, when done properly, will make your code more readable and maintainable and further increase productivity.
When naming your functions, it is important to not use slangs that only a few people would understand or trends that people can only relate to at a given time. Let your function names be descriptive enough, straight to the point and timeless.
A function should have only one
responsibility.
When you define your function, it is good practice to give it just one responsibility and make it do what its name suggests. This means that from our examples, choosing to sum two numbers while dividing every number in another tuple by two all in the same function would not be a good idea. Like we did, splitting the two actions into separate functions is better.
By doing this, you would not only improve your code readability, but you'll also make it easier to test and debug.
Summary
- A function is a set of statements designed to perform a particular task.
- During a function definition, the names that represent the values we intend to supply to the function are called
parameters
. - During a
function call
, the actual values provided to the function are calledarguments
. - The
return
statement is used to end the execution of a function while returning a specified value. - Variables that are defined inside a
function body
are locally scoped. This means that they can only be accessed inside the function definition. - An anonymous function is a function that has no name.
- To define an anonymous function, we use the
lambda keyword
, and to be able to reuse an anonymous function, it has to be assigned to a variable. - Function names should be descriptive, straight to the point and timeless.
- It is good practice to give your function just one responsibility.
Thanks for reading! If you still have trouble understanding the concept of functions, no worries; here's a link to The Simplest Explanation of Functions You’ll Ever Read.
Found this helpful? Please drop an emoji 💓, comment 📝 and share! 🎷
Here's my recent podcast on how to excel in your first year as a software engineer. I shared a few of my experiences in tech and the things I wish someone had told me during my first year as a software engineer: