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
- Assigned to variables.
- Passed as an argument to other functions.
- Returned from other functions.
- 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 addcourse
into thecourse_list
. func_add_courses("Power BI")
=> This called the function directly with its name to addPower 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")
=> Oncevariable_1
is referring to a function, then we can usevariable_1
to call thefunc_add_courses
. This will call the function and addPython
course tocourse_list
.- variable_2 = variable_1 => similarly, we can assign
variable_1
reference tovariable_2
. Nowvariable_2
will also refer to thefunc_add_courses
. variable_2("Generative AI")
=> This will call the function and addGenerative AI
course tocourse_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 andadd_course_function
function as an parameters.func_course_valid("Power BI", func_add_courses)
=> This passes functionfunc_add_courses
as an argument to functionfunc_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 returnfunc_add_courses
function.func_course_valid("Power BI")
=> This passes valid course as an argument to function and will returnfunc_add_courses
function. This returned function will be referenced by a variablereturn_func
.return_func("Power BI")
=> This makes a call to the return function which isfunc_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 functionfunc_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 thecourse_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:
- Takes another function as an argument.
- 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.