Python Functions: Explained for Beginners

Python Functions: Explained for Beginners

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 atupleand our function will receive a tuple of arguments for every argument supplied in place of the parameter during ourfunction 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 called arguments.
  • 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: