A first-class object in Python is an entity with all the properties of a Python variable, like integers, strings and other default and custom Python classes. It can be dynamically created and destroyed, passed to and returned from a function, stored in a data structure and more.

Python treats functions as first-class objects. This means you can assign a function to a variable, pass a function to another function, return a function from another function, store a function in a data structure and perform other tasks similar to any other Python object.

In this article, you’ll study, with the help of examples, how Python functions act as first-class objects.

The Conventional Way to Call Python Functions

If you’ve worked with Python, or any other programming language before, you know that conventional functions have two parts. You define a function and then call it via a function call. The following script demonstrates this.

def my_function(a, b):
    res = a + b
    return res

result = my_function(4, 6)
print(result)

Output:

10

However, Python functions can do a lot more than that. They possess all the characteristics of any ordinary Python object. Let’s explore this concept a bit more.

Python Functions as First-Class Objects

Storing Functions in Variables

You can store ordinary Python objects in variables. Likewise, you can store Python functions in variables.

To do this, you must define a Python function and assign its name (without parenthesis) to a variable. You can then call the function through its variable. You simply pass any arguments to the function via the function’s variable alias.

For example, the script below defines a function, my_function(), that returns the sum of the two parameters you pass to the function.

The my_function() variable is stored in the func_variable variable. To call the function, you must pass the function parameter values to the parenthesis that follow func_variable, jus tlike you would if that were the name of the function itself.

def my_function(a, b):
    res = a + b
    return res

func_variable = my_function

print(func_variable(10, 12))

Output:

22

Defining a function reserves some memory space for that function. Assigning a function to a variable merely creates a new pointer that references the original memory space.

If you delete the original function name, you can still access the function via its variables. For instance, the script below deletes the my_function() function.

del my_function
print(my_function)

Output:

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Input In [46], in <cell line: 2>()
      1 del my_function
----> 2 print(my_function)

NameError: name 'my_function' is not defined

However, even though the original function was deleted, you can still call my_function() via the function variable func_variable, as the following script proves.

print(func_variable(10, 12))

Output:

22

Passing a Function as a Parameter to Another Function

Just like ordinary Python objects, you can pass Python functions to other functions as parameter values.

For instance, the script below defines functions add(), mul(), and process_function().

The add() and mul() functions are passed as parameters to the process_function() function, which returns the result of the operation performed by add() or mul() functions.

def add(num1, num2):
    return num1 + num2

def mul(num1, num2):
    return num1 * num2


def process_function(my_func, val1, val2):

    result = my_func(val1, val2)
    return result

result = process_function(add, 4, 10)
print(result)

result = process_function(mul, 4, 10)
print(result)

Output:

14
40

Get Our Python Developer Kit for Free

I put together a Python Developer Kit with over 100 pre-built Python scripts covering data structures, Pandas, NumPy, Seaborn, machine learning, file processing, web scraping and a whole lot more - and I want you to have it for free. Enter your email address below and I'll send a copy your way.

Yes, I'll take a free Python Developer Kit

Nested Functions or Returning Function from Another Function

A Python function can have nested functions, which are functions defined inside another function. Moreover, you can return a Python function from another function.

The following script defines the make_circle_area_func() function that contains a nested circle_area() function. The make_circle_area_func() returns the circle_area() function.

def make_circle_area_func(pie):

    def circle_area(r):
        area = pie * (r * r)
        return area
    return circle_area
circle_area_func = make_circle_area_func(3.14)
circle_area = circle_area_func(2)
print(circle_area)

Output:

12.56

Storing Functions in a List

You can store objects and variables in Python data structures, like lists and dictionaries. In the same way, you can store Python functions in lists and dictionary collections, as well.

The following script demonstrates how to store three functions in a Python list. The script defines square(), cube(), and root() functions. A for loop iterates the list of functions and applies each function to integers from 1 to 5.

import math

def square(num):
    return num * num

def cube(num):
    return num * num * num

def root(num):
    return math.sqrt(num)


func_list = [square, cube, root]

for func in func_list:
    for i in range(1,6):
        print(func.__name__, i, "=", func(i))
    print("===========")

Output:

square 1 = 1
square 2 = 4
square 3 = 9
square 4 = 16
square 5 = 25
===========
cube 1 = 1
cube 2 = 8
cube 3 = 27
cube 4 = 64
cube 5 = 125
===========
root 1 = 1.0
root 2 = 1.4142135623730951
root 3 = 1.7320508075688772
root 4 = 2.0
root 5 = 2.23606797749979
===========

Storing Functions in a Dictionary

Storing functions in a dictionary is very similar to storing functions in lists. However, since dictionaries store items as key-value pairs, you’ll need to define keys for your functions.

The following code shows how to store multiple functions in a Python dictionary.

import math

def square(num):
    return num * num

def cube(num):
    return num * num * num

def root(num):
    return math.sqrt(num)


my_dic = {"square": square, "cube": cube, "root": root}

for k,v in my_dic.items():
    for i in range(1,6):
        print(k, i, "=", v(i))
    print("===========")

Output:

square 1 = 1
square 2 = 4
square 3 = 9
square 4 = 16
square 5 = 25
===========
cube 1 = 1
cube 2 = 8
cube 3 = 27
cube 4 = 64
cube 5 = 125
===========
root 1 = 1.0
root 2 = 1.4142135623730951
root 3 = 1.7320508075688772
root 4 = 2.0
root 5 = 2.23606797749979
===========

Objects as functions

Finally, you can also call an object as you would call a function i.e., write an object’s name followed by parentheses. To do so, you need to add a call() method to the object’s class.

The following script calls the Area class object, like you would call a function, to calculate the area of a circle.

class Area:

    def __init__(self, pie):
         self.pie = pie

    def __call__(self, r):
        return self.pie * (r * r)

circle_area = Area(3.14)
print(circle_area(2))

Output:

12.56

Get Our Python Developer Kit for Free

I put together a Python Developer Kit with over 100 pre-built Python scripts covering data structures, Pandas, NumPy, Seaborn, machine learning, file processing, web scraping and a whole lot more - and I want you to have it for free. Enter your email address below and I'll send a copy your way.

Yes, I'll take a free Python Developer Kit