Skip to content

An Introduction to Functions as Reusable Blocks of Code in Python

Updated: at 03:34 AM

Functions are one of the core building blocks in Python that allow you to write reusable, modular code. A function lets you group a series of Python statements together and give this block of code a name. You can then call or execute this function by name anywhere in your program whenever you need to perform that task.

Functions help break down complex problems into smaller, manageable pieces and avoid repetitive code. By using functions, you can improve readability and organize your code into logical sections with specific purposes. This introductory guide will provide a hands-on overview of Python functions to help you master this important programming concept.

Table of Contents

Open Table of Contents

What is a Function?

A function in Python is defined with the def keyword, followed by the function name and parentheses (). Any input parameters or arguments are placed inside the parentheses. The code block within every function starts with a colon : and is indented. Here is the basic syntax for a function in Python:

def function_name(parameters):
    statement 1
    statement 2

A function may or may not have parameters, which are variables defined locally within the function. The code statements contained inside the function make up the function body. These statements will execute whenever you call this function in your code.

You can also include a documentation string or docstring to briefly explain what the function does. Docstrings are written in triple quotes """ docstring """ right after the function definition.

For example:

def print_text(text):
  """Prints the input text to console"""


This function takes one parameter called text and simply prints it. The docstring explains what this little function does.

Functions need to be called to execute. You can call a function simply by writing its name followed by any required parameters in parentheses:

print_text("Hello World")

When Python executes this call, it will jump to the print_text function code and run all the statements inside it. This prints “Hello World” to the screen.

Function Benefits

Some key advantages of using functions are:

Well-designed functions are self-contained, performing a specific job independently of other code parts. This modularity makes programs easier to develop, read, test and debug.

Function Parameters and Arguments

The terms parameter and argument are often used interchangeably and both refer to the input variables of a function. However, these have subtle differences:

In the previous example, text is a parameter of the print_text() function while “Hello World” is the argument.

Parameters allow functions to accept input data and work dynamically with different kinds of arguments. Multiple parameters are separated by a comma inside the parentheses:

def multiply(x, y):
  result = x * y

This multiply() function has two parameters x and y. When calling the function, pass two arguments which get assigned to these parameters:

multiply(3, 5)

Here the arguments 3 and 5 are assigned to parameters x and y respectively. The function body executes using these values, multiplying them to print 15.

You can also specify default values for parameters while defining the function. This initializes parameters with a default argument if no value is passed for that parameter during function call.

For example:

def log(message, level="INFO"):
  print(f"{level}: {message}")

log("System starting") #INFO: System starting
log("Error", "ERROR") #ERROR: Error

Pass by Assignment

It is important to note that parameters in Python are passed by assignment. When you pass arguments to a function, they are bound to the names of the parameters in the function body. Any changes made to the parameters do not affect the arguments outside the function, since the parameters are treated as local variables in the function.

For example:

message = "Original message"

def change_message(msg):
  msg = "New message"

print(message) # Prints "Original message"

Here the message argument remains unchanged even after calling change_message() since parameter msg is treated as a local variable inside the function.

Return Values

Functions can process data and return a result back to the caller. Use the return keyword to return a value from the function.

For example:

def square(x):
  return x * x

num = 5
result = square(num)
print(result) # 25

The square() function returns the square of its argument. This return value gets assigned to result when we call square(num).

Return allows you to assign the function output to a variable or use it in expressions. A key point to remember is that the return statement immediately ends function execution. Any code after return is never executed.

By default, Python returns None if no return value is specified. You can also return multiple values from a function using tuples:

def square_cube(x):
  return (x*x, x*x*x)

sq, cb = square_cube(5)

This returns a tuple with square and cube of 5 assigned to sq and cb.

The pass Statement

In some cases, you may need to define a dummy function that does nothing. This is done by using the pass statement which acts as a placeholder.

For example:

def empty_function():

pass simply does nothing and can be used for minimal empty bodies when you have not written the actual code yet but want to implement the function definition.

Documenting Functions

Good documentation is the hallmark of well-written code. Documentation makes code easier to understand and use. Python supports documentation strings or docstrings that allow you to describe what a function does.

Write docstrings right after the function definition using triple quotes. The first line should be a short concise summary of the function while other lines can elaborate on it.

For example:

def square(number):
  """Returns the square of a given number

  This function takes a numeric value, squares it
  and returns the result.

  return number * number

You can access the docstring of a function using the __doc__ attribute:


This prints the contents of the docstring for users to read.

Docstrings are a useful way to document your functions and also let others know how to use them. The Python style guide PEP 257 covers docstring conventions in detail. Follow these standards to make your code more readable.

Types of Functions

Broadly, functions can be categorized into two types:

  1. Built-in functions - These are predefined functions included in Python like print(), len(), range() etc.

  2. User-defined functions - Functions defined by you, the programmer, to serve a specific purpose.

Functions can also be further classified based on their return value as:

  1. Fruitful functions - Returns a value or values using return. Most functions are fruitful functions.

  2. Void functions - Executes a task but does not return anything. Uses return without any value or simply ends without it.

Let’s look at examples of the different types of functions in Python.

Built-in Functions

Python comes packed with numerous built-in functions ready for you to use. These functions perform common tasks like input/output, type conversions, mathematics, variable manipulations and more.

Some commonly used built-in functions include:

print() # Prints to console

len() # Returns length of an object

int() # Converts to integer

float() # Converts to float

round() # Rounds a number

sum() # Sums elements of an iterable

These built-in functions help save time and effort since many basic operations are already implemented for you. Check out the full list of built-in functions in the Python Standard Library.

User-Defined Functions

These are functions defined by you for your applications. User-defined functions help break down complex problems into logical reusable chunks.

For example, a function to calculate simple interest:

def simple_interest(p, r, t):
  """Calculates simple interest"""

  interest = (p * r * t) / 100
  return interest

amount = simple_interest(100, 0.05, 5)
print(amount) # 2.5

The simple_interest() function encapsulates the simple interest logic in a reusable way. We can call it anywhere, with varying inputs, to calculate simple interest.

Writing good user-defined functions is a skill you will gradually develop with experience. Focus on making small single-purpose functions that do one thing well.

Fruitful and Void Functions

Fruitful functions return a meaningful value using return while void functions do not return anything useful.

For example:

# Fruitful function
def get_name():
  return "John"

name = get_name()

# Void function
def print_name():

print_name() # No return

get_name() is a fruitful function since it returns a string while print_name() is a void function that just prints without a return value.

In general, fruitful functions are more common. But void functions are sometimes useful for executing side-effects like printing, logging, updating variables, etc.

Scope and Lifetime of Variables

Variables defined inside a function are in the local scope of that function. They cannot be accessed from outside the function. Let’s examine this through an example:

message = "Global"

def print_message():
  message = "Local"


This will print “Local” followed by “Global” because both message variables are treated independently. The global message remains unchanged.

Parameters are also local variables scoped to the function. Any variables assigned inside the function are local too. Local variables have function scope - they only exist within the function and cannot be used elsewhere.

Lifetime refers to how long a variable exists before being destroyed. In Python, local variables are destroyed once the function call completes. Next time you call the function, new local variables are created. This helps prevent accidentally modifying local state from other parts of the program.

Modular Programming

Complex systems are easier to manage when broken down into smaller modular units. Functions allow you to modularize code by separating concerns into self-contained logical chunks.

Modular programming principles recommend building software divided into distinct modules like functions or classes. These modules have clearly defined purposes, are well-encapsulated, and interact through fixed interfaces.

For example, consider a module to work with complex numbers:

"""Complex math module"""

def add_complex(a, b):
  """Adds two complex numbers"""

  return (a[0] + b[0], a[1] + b[1])

def mul_complex(a, b):
  """Multiplies two complex numbers"""

  return (a[0]*b[0] - a[1]*b[1], a[0]*b[1] + a[1]*b[0])

This module contains two functions to operate on complex numbers represented as tuples. We encapsulate the complex math inside functions instead of writing everything in a linear script. The functions provide logical boundaries between steps.

Other parts of the program can import and use this module without worrying about the internal implementations. We can test and reuse these functions easily. This demonstrates the advantages of modular programming using functions.

Recursive Functions

A recursive function is one that calls itself recursively. They are used to solve problems that can be broken down into simpler subproblems of the same kind.

For example, calculating factorial:

def factorial(x):
  if x == 1:
    return 1
    return x * factorial(x-1)

print(factorial(5)) # 120

The factorial function calls itself to compute the factorial recursively. The recursion ends when we reach the base case of x = 1.

Some key properties of recursive functions are:

Recursion provides an alternative, elegant way to solve certain problems compared to iterative solutions. However, we must be careful to define the base condition correctly to end the recursion.


Functions are core building blocks in Python that let you define reusable pieces of code to perform specific tasks. They provide several advantages like modularity, encapsulation, abstraction, and reusability in code.

This guide covered all the key aspects of using functions effectively:

Learning to design and utilize functions is an important skill for structured programming. With practice, you will be able to leverage functions to develop clean, maintainable Python programs.