Python Functions as First-Class Objects (with Examples)

In Python, functions are considered first-class objects (or first-class citizens), meaning they can be treated like any other object, such as integers, strings, lists, etc. This property allows Python developers to use functions as building blocks for writing flexible and reusable code.

Python Functions – First-Class Objects

In Python, functions are first-class objects, meaning they can be treated like any other object such as integers, strings, or lists. This feature allows for a flexible programming model, enabling powerful constructs such as passing functions as arguments, returning them from other functions, and more.

Characteristics of First-Class Objects in Python – Functions as first-class objects can be

  1. Assigned to variables.
  2. Passed as an argument to other functions.
  3. Returned from other functions.
  4. Stored in data structures such as lists, dictionaries, etc.

Assigning Functions to Variables

Just like how we assign a number or string to a variable, we can also assign a function to a variable and call it using that variable.

# first class functions can be stored in a variable
courses_list = []

# define a function to add course into a course list
def func_add_courses(course):
	courses_list.append(course)
	print(course, "added to the course list")

func_add_courses("Power BI")             # direct call to a function

variable_1 = func_add_courses  # function reference assigned to a variable
variable_1("Python")           # call to a function using variable reference

variable_2 = variable_1        # variable reference assigned to second variable
variable_2("Generative AI")    # call to a function using second variable reference

print(courses_list)  # Output => ['Power BI', 'Python', 'Generative AI']
  • In this example, we have defined a function func_add_courses(course) to add course into the course_list.
  • func_add_courses("Power BI") => This called the function directly with its name to add Power BI as course.
  • variable_1 = func_add_courses => This assigns the function reference to a variable. This assignment is very similar as we assigned any other object reference to a variable.
  • variable_1("Python") => Once variable_1 is referring to a function, then we can use variable_1 to call the func_add_courses. This will call the function and add Python course to course_list.
  • variable_2 = variable_1 => similarly, we can assign variable_1 reference to variable_2. Now variable_2 will also refer to the func_add_courses.
  • variable_2("Generative AI") => This will call the function and add Generative AI course to course_list.
  • course_list will have three courses added to it => [‘Power BI’, ‘Python’, ‘Generative AI’]

Functions Passed as Arguments to Other Functions

In Python functions are objects, we can pass them as arguments to other functions, allowing for higher-order functions that accept and operate on other functions.

# first class functions can be passed to another function as an argument

courses_list = []

# define a function to add course into a course list
def func_add_courses(course):
	courses_list.append(course)
	print(course, "added to the course list")

# define a function to check if course is valid or not
def func_course_valid(course, add_course_function): # takes course and another function as parameter
	if len(course) > 0:
		add_course_function(course)         # call the function given as an argument
	else:
		print("given course is not valid")

# call to function with valid course and another function as argument
func_course_valid("Power BI", func_add_courses)  # func_add_courses as argument
# call to function with invalid course and another function as argument
func_course_valid("", func_add_courses)          # func_add_courses as argument
# call to function with valid course and another function as argument
func_course_valid("Python", func_add_courses)    # func_add_courses as argument

print(courses_list) # Output => ['Power BI', 'Python']
  • In this example, func_add_courses(course) function adds a course to the course_list.
  • func_course_valid(course, add_course_function) => This is second function, which takes course and add_course_function function as an parameters.
  • func_course_valid("Power BI", func_add_courses) => This passes function func_add_courses as an argument to function func_course_valid. This is how functions are passed as an argument to other functions

Functions Returned from Other Functions

Functions can return other functions. This allows for the creation of higher-order functions.

# first class functions can be returned from another function

courses_list = []
# define a function to add course into a course list
def func_add_courses(course):
	courses_list.append(course)
	print(course, "added to the course list")

# define a function to check if course is valid or not
def func_course_valid(course):    # takes course as parameter
	if len(course) > 0:
		return func_add_courses   # return another function
	else:
		print("given course is not valid")

return_func = func_course_valid("Power BI") # This function returns another function
return_func("Power BI")                     # call to returned function

return_func = func_course_valid("Python")  # This function returns another function
return_func("Python")                      # call to returned function

return_func = func_course_valid("")         # Invalid course, will not return function
try:
	return_func("")                         # call to function will raise NameError and TypeError
except (NameError, TypeError) as err:
	print("error", err)

print(courses_list) # Output => ['Power BI', 'Python']
  • In this example, func_add_courses(course) function adds a course to the course_list.
  • func_course_valid(course) => This is second function, which takes course as parameter. If the course is valid then it will return func_add_courses function.
  • func_course_valid("Power BI") => This passes valid course as an argument to function and will return func_add_courses function. This returned function will be referenced by a variable return_func.
  • return_func("Power BI") => This makes a call to the return function which is func_add_courses.

Functions Stored in Data Structures

We can store functions in data structures like lists or dictionaries, and call them from those structures.

# first class functions can be stored in data structures like list, set, dictionary etc.

courses_list = []
# define a function to add course into a course list
def func_add_courses(course):
	courses_list.append(course)
	print(course, "added to the course list")

# create a key-value pair dictionary
func_dict = {func_add_courses:["Python", "Power BI", "Generative AI"]} # function as a key and list of courses
print(func_dict) 
# Output => {<function func_add_courses at 0x000001E75835A2A0>: ['Python', 'Power BI', 'Generative AI']}

# loop through the keys of dictionary
for key in func_dict:             # Here key is the function in dictionary
	for course in func_dict[key]: # loop list stored at dictionary key
		key(course)               # call the function to add course to the course_list

print(courses_list) # Output => ['Python', 'Power BI', 'Generative AI']
  • In this example, func_add_courses(course) function adds a course to the course_list.
  • func_dict = {func_add_courses:["Python", "Power BI", "Generative AI"]} => This defines the dictionary with key as function func_add_courses and value as list of courses. This stores the function into a collection object.
  • key(course) => We will loop through the dictionary key-values and call the key-function to add course to the course_list.
  • course_list has all three courses added to it => [‘Python’, ‘Power BI’, ‘Generative AI’]

Closures in Python

A closure is a function that retains the values of the variables from its enclosing scope, even after the outer function has finished executing. This is a direct result of functions being first-class objects.

# Closures in Python
def outer_function(text):
    def inner_function():
        return text  # The inner function remembers 'text' even after 'outer_function' finishes.
    return inner_function

my_closure = outer_function("courses@shbytes.com")
print(my_closure())  # Output: courses@shbytes.com

In this example, my_closure retains access to the variable text from outer_function, even though outer_function has finished execution. Closures allow for the creation of more advanced function objects that “remember” their environment.

Higher-Order Functions

A higher-order function is a function that either:

  1. Takes another function as an argument.
  2. Returns a function as its result.

We’ve already seen examples of higher-order functions, such as passing a function as an argument to another function. These are extremely useful in scenarios like decorators, event handling, or callbacks.

# Higher-Order Functions
def apply_thrice(func, argument):
    return func(func(func(argument)))  # return function called 3 times

def add_ten(x):
    return x + 10

# Using 'apply_thrice' with 'add_ten'
result = apply_thrice(add_ten, 20)  # This will add 10 to 20 thrice
print(result) # Output => 50

In this example, apply_thrice is a higher-order function that applies add_ten to the argument thrice, demonstrating how functions can be passed around and called dynamically.

Real-World Use Cases: Functions as First-Class Objects

One of the most common uses of first-class functions is in decorators. Decorators take advantage of the fact that functions can be passed around and returned, allowing us to modify the behavior of a function dynamically.

Decorators

Decorators are a common example of higher-order functions & first class objects that modify or enhance the behavior of other functions. They are widely used in frameworks like Flask and Django.

def shbytes_decorator(func):
    def wrapper():
        print("Do something before the function")
        func()
        print("Do something after the function")
    return wrapper

@shbytes_decorator
def say_shbytes():
    print("shbytes.com")

say_shbytes()

Program Output

Do something before the function
shbytes.com
Do something after the function

Callbacks

Functions are often passed as arguments in event-driven programming as callbacks. For instance, in GUIs, a function can be passed as a callback to respond to a button click event.

Functional Programming

In functional programming paradigms, functions are treated as values. Libraries like functools and itertools in Python leverage higher-order functions for things like function composition and partial application.

Summary

In Python, the concept of functions as first-class objects provides powerful capabilities for writing clean, reusable, and flexible code. This allows functions to be assigned to variables, passed as arguments, returned from other functions, stored in data structures, and more. By understanding and utilizing this concept, we can unlock a range of possibilities in Python, from building complex systems using decorators and callbacks to functional programming techniques.

This characteristic of Python is fundamental to many advanced programming techniques, and mastering it will greatly enhance our Python development skills.

Following topics were covered in this article:

Code – Github Repository

All code snippets and programs for this article and for Python tutorial, can be accessed from Github repository – Comments and Docstring in Python.

Python Topics


Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *