Defining Your Own Python Function

Defining Your Own Python Function

by Leodanis Pozo Ramos Updated Reading time estimate 1h 9m basics python

A Python function is a named block of code that performs specific tasks and can be reused in other parts of your code. Python has several built-in functions that are always available, and you can also create your own. These are known as user-defined functions.

To define a function in Python, you use the def keyword, followed by the function name and an optional list of parameters enclosed in a required pair of parentheses. You can call and reuse a function by using its name, a pair of parentheses, and the necessary arguments.

Learning to define and call functions is a fundamental skill for any Python developer. Functions help organize your code and make it more modular, reusable, and easier to maintain.

By the end of this tutorial, you’ll understand that:

  • A Python function is a self-contained block of code designed to perform a specific task, which you can call and reuse in different parts of your code.
  • You can define a Python function with the def keyword, followed by the function name, parentheses with optional parameters, a colon, and then an indented code block.
  • You call a Python function by writing its name followed by parentheses, enclosing any necessary arguments, to execute its code block.

Understanding functions is key to writing organized and efficient Python code. By learning to define and use your own functions, you’ll be able to manage complexity and make your code easier to read.

Take the Quiz: Test your knowledge with our interactive “Defining Your Own Python Function” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Defining Your Own Python Function

In this quiz, you'll test your understanding of defining and calling Python functions. You'll revisit the def keyword, parameters, arguments, and more.

Getting to Know Functions in Python

In mathematics, a function is a relationship or mapping between one or more inputs and a set of outputs. This concept is typically represented by the following equation:

Math Function

Here, f() is a function that operates on the variables x and y, and it generates a result that’s assigned to z. You can read this formula as z is a function of x and y. But how does this work in practice? As an example, say that you have a concrete function that looks something like the following:

Add Function

Now, say that x is equal to 4 and y is 2. You can find the value of z by evaluating the function. In other words, you add 4 + 2 to get 6 as a result. That’s it!

Functions are also used in programming. In fact, functions are so fundamental to software development that virtually all modern, mainstream programming languages support them. In programming, a function is a self-contained block of code that encapsulates a specific task under a descriptive name that you can reuse in different places of your code.

Many programming languages have built-in functions, and Python is no exception. For example, Python’s built-in id() function takes an object as an argument and returns its unique identifier:

Language: Python
>>> language = "Python"
>>> id(language)
4390667816

The integer number in this output uniquely identifies the string object you’ve used as an argument. In CPython, this number represents the memory address where the object is stored.

Note how similar this notation is to what you find in mathematics. In this example, language is equivalent to x or y, and the pair of parentheses calls the function to run its code, comparable to evaluating a math function. You’ll learn more about calling Python functions in a moment.

Similarly, the built-in len() function takes a data collection as an argument and returns its length:

Language: Python
>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> items = len(numbers)
>>> items
10

In this example, the list of numbers has ten values, so len() returns 10. You assign this value to the items variable, which is equivalent to z in the mathematical equation you saw before.

Most programming languages—including Python—allow you to define your own functions. When you define a Python function, you decide whether it takes arguments. You’re also responsible for how the function internally computes its result.

Once you’ve defined a function, you can call it from different parts of your code to execute its specific computation or action. When the function finishes running, it returns to the location where you called it.

With this quick introduction to Python functions, you’re ready to dive deeper into creating and using functions in your code. First, you’ll examine some of the main benefits of using functions.

Exploring Some Benefits of Functions

So, why should you bother defining and using functions in Python? What are their benefits? There are several good reasons to define and use functions in your code. In the following sections, you’ll explore some of these benefits.

Abstraction

Abstraction is about managing complexity by exposing a simplified interface to the user or programmer, while keeping the internal workings of a piece of code private or irrelevant to the context of use. You can do this by hiding a given functionality inside a function and exposing only the function’s interface, consisting of its name and expected arguments, to the rest of the program.

For example, in previous sections, you used some Python built-in functions even though you don’t know how they’re implemented internally. You only knew the function’s name and its arguments. So, built-in functions abstract the implementation details and only show you a user-friendly interface.

Defining custom functions enriches your vocabulary by introducing new black boxes that the language didn’t originally have. This increases your code’s readability by using descriptive function names that unambiguously identify specific tasks, rather than using long sequences of statements without an obvious, visible goal.

Encapsulation

Encapsulation refers to bundling data and behaviors into a single unit and restricting direct access to some of these components.

When you call a function, Python creates a dedicated namespace for that function call. This namespace will hold the names you define inside the function. It’s a namespace distinct from all other existing ones, such as the global and built-in namespaces.

The practical upshot of this behavior is that the variables defined within a function are only accessible from within the function itself, which allows for data encapsulation.

Even when function’s local variables have the same names as outer variables, there will be no confusion or interference because they’re in separate namespaces. So, you can’t modify the function’s behavior by altering the value of a given local variable from the outside, whether by accident or on purpose.

Modularity

Modularity is a design principle that divides a program into separate, independent, and interchangeable components. Each component is a self-contained unit that encapsulates a specific part of the program’s functionality.

Functions allow you to divide a large program into smaller chunks that perform a specific task, making your code modular.

Imagine, for example, that you have a program that reads in a file, transforms its contents, and writes the result to a different file. You could handle these operations as a plain sequence of statements:

Language: Python
# Main program

# Read the file
<statement_0>
<statement_1>
...
<statement_n>

# Process the file
<statement_0>
<statement_1>
...
<statement_n>

# Write the result to another file
<statement_0>
<statement_1>
...
<statement_n>

In this example, your program is a bunch of sequential statements, with whitespace and comments to help organize it. However, if the code were to get much longer and more complex, then you’d have an increasingly difficult time wrapping your head around it.

Alternatively, you could structure the code as shown below:

Language: Python
def read_file():
    <statement_0>
    <statement_1>
    ...
    <statement_n>

def process_file():
    <statement_0>
    <statement_1>
    ...
    <statement_n>

def write_file():
    <statement_0>
    <statement_1>
    ...
    <statement_n>

# Main program
read_file()
process_file()
write_file()

In this example, you modularize the code. Instead of all the code being strung together, it’s broken into separate functions, each focusing on a specific task. Those tasks are read, process, and write. The main program now calls each of these functions in turn.

As programs become more complicated, modularizing them with functions becomes increasingly beneficial. Breaking a task into smaller subtasks helps you manage complex programming problems. It also facilitates debugging because you can focus on simpler tasks that are often easier to debug than complex and overly long tasks.

Reusability

Reusability is the ability to use existing code in new contexts without repeating the code itself. It implies writing code in a way that allows you to use it multiple times across different parts of a program, or even across multiple projects, with little or no modification.

Suppose you’ve written some code that does something useful. As you continue development, you find that the code performs a task you often need in many different locations within your program. What should you do?

Say that you decide to replicate the code over and over again, using your editor’s copy-and-paste capability. What would happen if you later realize that the piece of code in question must be modified or updated? If copies of the code are scattered all over your program, then you’ll need to make the necessary changes in every location.

Code duplication can lead to another issue. If a developer updates most but not all instances of the repeated code, this can result in inconsistencies in data or behavior across the program.

A better solution is to define a Python function that performs the task. Then, you can call the function from any part of your program that you need to accomplish the task. Down the line, if you decide to change how the code works, then you only need to change the code in one location: the function’s definition. The changes will automatically be picked up anywhere you call the function.

The don’t repeat yourself (DRY) principle of software development is a strong motivation for using functions. Functions help eliminate repetitive code. They also allow you to align with other core software engineering principles, such as the single-responsibility principle (SRP).

Maintainability

In programming, maintainable code refers to code that you can quickly and easily understand, correct, enhance, or adapt over time. A maintainable codebase is clear, well-structured, and modular, allowing developers to make changes with minimal risk of introducing bugs.

Functions help with code maintainability because they allow you to do the following:

  • Break down code into logical parts
  • Encourage reuse and consistency
  • Reduce duplication and errors
  • Facilitate testing and debugging
  • Encourage clear documentation

In short, functions are a great tool for writing maintainable code. This type of code is easier to improve and scale with new features, which is often a common need.

Testability

Testability refers to how easy it is to effectively test a piece of code to ensure it behaves as expected. You have a piece of testable code if it’s straightforward to write automated tests that verify its correctness.

Writing functions with clear arguments and explicit return values makes your code easier to test and predict. When you avoid side effects in your functions and follow the single responsibility principle, they become easier to reason about. Additionally, keeping your functions small and readable further enhances their quality. Together, these practices greatly improve the testability of your code.

Defining Functions in Python

Now it’s time to start defining your own functions in Python. The general syntax for defining a function is shown below:

Language: Python Syntax
def function_name([parameters]):
    <block>

Below, you have a breakdown of this syntax’s components:

Component Description
def The keyword that begins the function definition
function_name A valid Python identifier that names the function
[parameters] An optional, comma-separated list of formal parameters for the function
: The punctuation that denotes the end of the function header
<block> The function’s code block

The final item, <block>, is usually called the function’s body. The body is a series of statements that will run when you call the function. The body is defined by indentation. This is the same as code blocks associated with a control structure, like an if or while statement.

Here’s your first Python function:

Language: Python
>>> def greet(name):
...     print(f"Hello, {name}!")
...