Functions in Python

Andrei Maksimov

Andrei Maksimov

0
(0)

In any programming language function is a reusable block of code that allows us to implement repetitive tasks in the code without code duplication. Functions allow you to write clean, organized, and manageable code. This article covers functions in Python, their syntax, arguments, return statements, function annotations, and many more.

Types of functions

There are two types of functions in Python:

  • built-in functions
  • user-defined functions

Built-in functions available for you with Python distribution out of the box and allow you to perform various different tasks:

  • Math operations
  • Type conversion
  • Managing iterators
  • Managing composite data types
  • Working with classes
  • Manage variables, references, and scope

Any functions that Python developers declare in their code are called user-defined functions, and those functions are the primary focus of this article.

Function syntax

Here’s a syntax for defining Python function:

def <function_name>([parameters]):
    """optional docstring"""
    code_statement(s)
    [return [expression]]

Here’s a description of the most important parts of the function definition:

  • def – keyword used for defining the function name and optional parameters
  • <function_name> – name of the function
  • [parameters] – optional comma-separated list of parameters that the function may need to accept
  • """optional docstring""" – optional documentation string of the function
  • code_statement(s) – one or more lines of code that are implementing the logic of the function
  • [return [expression]] – optional statement that allows to return something from the function

All code_statement(s) are forming Python function body and should the same level of indentation.

Simple Python function

Let’s create a simple function to illustrate the Python execution flow:

def my_function():
    """This function prints a message"""
    message = '* Code executed during function call *'
    print(message)

print('Code executed before function call')
my_function()
print('Code executed after function call')
1. Functions in Python - Simple function execution

Now, let’s take a look, how Python process this code:

Every single time you’re calling a function in your program, Python will execute the same piece of code from the function body.

Empty Python function

Sometimes, you may need to define an empty function, for example, not to forget to implement something later.

In that case, you can use a pass statement.

Such definition usually called a function placeholder or a stub:

def my_function():
    pass

my_function()

Such definition allows you to call a function from your code, but nothing is going to happen:

2. Functions in Python - Placeholder

Function arguments

You need to use function arguments when you have a need to pass data into your function.

Let’s review all types of arguments one by one.

Positional arguments

The most common way to define arguments for a Python function is using positional arguments (or required arguments). In the function definition, you specify a comma-separated list of parameters inside parentheses:

def perform_calculation(a, b, c):
    result = a + b * c
    print(f'Calculation result: {result}')

perform_calculation(1, 2, 3)
3. Functions in Python - Positional arguments

In the example above, during function call Python sets values to variables in the following way:

All arguments we specified in the function definition have to be provided to the function when you’re calling it.

If you provide fewer arguments, you’ll get the following error message:

Traceback (most recent call last):
   File "functions/positional_arguments.py", line 7, in 
     perform_calculation(1, 2)
 TypeError: perform_calculation() missing 1 required positional argument: 'c'

If you provide more arguments, you’ll get a slightly different error message:

Traceback (most recent call last):
   File "functions/positional_arguments.py", line 7, in 
     perform_calculation(1, 2, 3, 4)
 TypeError: perform_calculation() takes 3 positional arguments but 4 were given

Keyword arguments

When you’re defining a function, you can specify arguments in the form <argument>=<value>.

Such syntax allows you to specify default values for the function arguments, for example:

def perform_calculation(a=1, b=1, c=1):
    result = a + b * c
    print(f'Calculation result: {result}')

perform_calculation(1, 2, 3)
perform_calculation(b=1, a=2, c=3)
perform_calculation(a=2, c=4)
perform_calculation()
4. Functions in Python - Keyword arguments

As you can see from the execution results:

  • Python assigns all values provided during the function call to the function arguments in order
  • Any values specified in the <argument>=<value> format will be assigned only to specific function arguments
  • If no value provided for the function argument, Pyhton will use default argument value

An unexpected argument for the function, for example:

perform_calculation(a=1, b=2, c=3, d=2)

Will lead to the following error message:

Traceback (most recent call last):
   File "functions/keyword_arguments.py", line 13, in 
     perform_calculation(a=1, b=2, c=3, d=2)
 TypeError: perform_calculation() got an unexpected keyword argument 'd'

It is important to keep in mind, that positional arguments can not follow keyword arguments.

If you call the function in the following way:

perform_calculation(a=1, b=2, 3)

You’ll get the following error message:

File "functions/keyword_arguments.py", line 13
     perform_calculation(a=1, b=2, 3)
                                  ^
SyntaxError: positional argument follows keyword argument

Reference vs value

There are two types of objects available in Python:

  • Mutable – list, dictionary, set and user-defined classes
  • Immutable – int, float, decimal, bool, string, tuple, and range

Python passes all immutable objects to the function by value, which means, that if you modify an immutable object within the function, its value will remain unchanged outside of the function:

a = 1

def my_function(my_argument):
    my_argument = 2

print(f'a = {a}')
6. Functions in Python - Immutable object argument

On another side, Python assigns mutable objects to variables by reference.

That means, if you modify mutable object within the function, object changes will be accessible outside of the function:

a = []

def my_function(my_list):
    my_list.append('*')

my_function(a)

print(f'a = {a}')
7. Functions in Python - Mutable object argument

Mutable defualt arguments

We can use mutable objects as default values for the function arguments, for example:

def my_function(my_list=[]):
    my_list.append('*')
    print(f'my_list values: {my_list}')

my_function(['*'])
my_function(['*'])
5. Functions in Python - Mutable objects as default argument values

Nothing strange is happening, our function is adding elements to the list as expected.

Now let’s take a look, what is going to happen if we will call the same function without arguments:

def my_function(my_list=[]):
    my_list.append('*')
    print(f'my_list values: {my_list}')

my_function()
my_function()
8. Functions in Python - Mutable objects as default argument values

In the example above, as soon as we did not provide any arguments to the function, Python created a mutable list during the first function call and continue using it for all other calls.

In summary, you should be extra careful when you’re modifying mutable objects within your code.

Return statement

Any function in Python can have optional return statement that exits a function and optionally passing back an expression to the caller.

Here’s the return statement syntax:

return [expression]

Let’s modify one of our previous examples to illustrate how does the return statement work:

def perform_calculation(a, b, c):
    result = a + b * c
    return result

b = perform_calculation(1, 2, 3)

print(f'Function returned: {b}')
9. Functions in Python - Return statement

Note: A return statement with no arguments is the same as return None.

Arbitrary arguments

Positional and keyword arguments allow us to pass a limited amount of arguments to the function.

But what if we need a function to process command-line arguments, and we cannot predict how many arguments the function will get?

To solve this specific problem, Python provides us with arbitrary arguments:

def function_name([arguments,] *args, **kwargs):
    """function_docstring"""
    code_statement(s)
    [return expression]

Here:

  • *args – arbitrary list of positional arguments (tuple)
  • **kwargs – arbitrary list of keyword arguments (dict)

Here’s how you’re processing those arguments:

def print_args(x, *args, **kwargs):
    """Function prints all passed arguments"""

    print(f'x = {x}')

    print('Printing arbitrary positional arguments:')
    for arg in args:
        print(f'arg = {arg}')

    print('Printing arbitrary keyword arguments:')
    for kw in kwargs:
        print(f'{kw} = {kwargs[kw]}')

print_args(1, 2, 3, y=4, name='Andrei')
10. Functions in Python - Arbitrary arguments

Assigning function to a variable

In Python, everything is an object, and function is not an exception.

That means, you can assign a function to a variable and use this variable to call the function:

def my_sum(x, y):
    return x + y

my_sum_2 = my_sum

result = my_sum_2(1, 2)

print(f'Result: {result}')
12. Functions in Python - Assigning function to variable

Passing function as an argument

As soon as we can assign functions to variables, it becomes possible to pass function as an argument to another function:

def my_sum(*args):
    result = 0
    for arg in args:
        result += arg
    return result

def my_mult(*args):
    result = 1
    for arg in args:
        result *= arg
    return result

def my_calc(func, *args):
    return func(args)

sum_result = my_calc(my_sum, 1, 2)
mult_result = my_calc(my_mult, 3, 4)

print(f'Sum: {sum_result}')
print(f'Mult: {mult_result}')
13. Functions in Python - Passing function as an argument

In the example above, function my_calc applies my_sum or my_mult function to calculate the sum or multiplication result of all provided arguments.

Anonymous or lambda functions

Now, we can extend the concept of assigning a function to a variable by introducing anonymous or lambda functions.

These functions are called anonymous because they are declared in a non-standard way (without using the def keyword).

Instead of using def keyword, we’re using lambda keyword to create them.

Here are some notes about lambda functions in Python:

  • It can take any number of arguments but it returns only one value
  • It can not contain commands or multiple expressions
  • Lambda function is a short one-line function

The syntax of the lambda function in Python:

lambda [arg_1[, arg_2, ..., arg_n]]: expression

Now, let’s implement a simple lambda function, that sums two arguments:

my_sum = lambda x, y: x + y;

result = my_sum(1, 2)

print(f'Result: {result}')
11. Functions in Python - Lambda functions

Line 1 from the example above is equivalent to the following normal function definition:

def my_sum(x, y):
    return x + y

Python function annotations

Function annotation is a feature of Python for documenting a function.

Annotations provide a way to attach metadata to a function’s parameters and return value:

def my_sum(x: int, y: int) -> int:
    return x + y

Such syntax allows developers to get a better understanding of what type of parameters does the function expects and what type of result it should return.

This annotation information is available at __annotations__ attribute of the function:

14. Functions in Python - Annotations

You may use more complex types to annotate your functions:

def my_sum(
    x: {
        'description': 'first argument',
        'type': int
    },
    y: {
        'description': 'second argument',
        'type': int
    }) -> \
    {
        'description': 'sum of x and y',
        'type': int
    }:
    return x + y

sum_result = my_sum(1, 2)

print(f'Sum: {sum_result}')

print(f'Annotations: {my_sum.__annotations__}')
15. Functions in Python - Annotations (dict)

Summary

In this article, we covered almost everything you need to know about functions in Python including functions types, syntax, positional, keyword and arbitrary arguments, return statements, In addition to that, we’ve provided lots of additional examples to cover assigning function to a variable, passing a function as an argument, anonymous or lambda functions, and function annotations.

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Subscribe to our updates

Like this article?

Share on facebook
Share on Facebook
Share on twitter
Share on Twitter
Share on linkedin
Share on Linkdin
Share on pinterest
Share on Pinterest

Want to be an author of another post?

We’re looking for skilled technical authors for our blog!

Leave a comment

If you’d like to ask a question about the code or piece of configuration, feel free to use https://codeshare.io/ or a similar tool as Facebook comments are breaking code formatting.