Article Agenda
This article is focused at making you understand the property of functions to behave as first class objects. We will cover the following:
Introduction
You might have heard of the famous saying, "In Python, everything is an object". Very confusing as it may sound, this is absolutely true. In Python, every single entity is represented as an object ( Yes, object from the OOP. In case you don't know about OOP, I have got it briefly covered in this article ). This concept has given rise to many methodologies and principles in Python like Closures and Decorators.
Psst.. If you are in a hurry, you can watch the video version of this post instead
Alright, let's get started.
First Class Object
To keep it short and simple, A first-class object is an entity within a programming language that can:
- Appear in an expression
- Be assigned to a variable
- Be used as an argument
- Be returned by a function call
So, what do you think would be candidates to this? Well, Python datatypes fit these criteria, so datatypes like Integer, String, Boolean etc are first-class objects. So, let me ask: Are loops and conditionals first-class objects? Of course not since they both are failing multiple criteria. Finally, we can achieve all the aforementioned with functions as well! Therefore, functions are also first-class objects.
First Class Functions
In programming languages like Python, JavaScript, we have functions as First-Class Objects. Hence, the formal name of a function is First-Class Function (although we just call it function). First-Class Functions can be treated as any other object. This means that in Python, functions can be passed around, tossed in as arguments to other functions and even be assigned to variables.
Given below is a function which increments a number by 1:
def plusOne(number):
return number+1
Now to prove that functions can be treated as other objects, let me go ahead and rename this function like so:
def plusOne(number):
return number+1
#renaming the above function
re = plusOne
#calling both the functions
plusOne(10) # 11
re(10) # 11
You'd notice that both of them gives you the same output. Do you remember encountering this behavior elsewhere? Well, if you run the following code, you might get an idea:
x = 11
y = x
print(x) # 11
print(y) # 11
Surprising ain't it? Therefore, functions behave like the first-class objects. This is something unique that other programming languages like C, C++ never had. Functions in Python can be treated as first class objects (String, Integer, etc).
Now, I am going to spice things up. This might seem a bit weird in the beginning but you will understand it and grasp the concept pretty quick.
If you remember that we can store the First Class Objects in some other data structure like Lists, Dictionaries right? Well, this means that a function too can be stored in these data structures and used accordingly. Let me explain this more briefly (using List as the data structure):
def plusOne(number):
return number+1
def plusTwo(number):
return number+2
def plusThree(number):
return number+3
def plusFour(number):
return number+4
# list storing function objects
func_list = [plusOne, plusTwo, plusThree, plusFour]
# executing each function
for func in func_list:
print(func(10))
# It will print out ---> 11, 12, 13, 14
In the above snippet, I have created a func_list
list which will store the function objects. Now, before I move further, it is imperative to understand that Python does not make a call to the function unless you succeed it with brackets ()
. So, if I only do this:
print(plusOne)
# prints out ---> <function plusOne at 0x000001B4FC7FEF70>
Python would only give me the function reference as shown above. Alright, let's go back. Now, the func_list
holds the function objects (which are not yet executed). Then, I ran a for loop, accessed each function and then finally executed it with the help of parenthesis and a parameter, 10.
Great stuff! I believe now you got to know what the original behavior of functions are. To truly solidify your grasp on this concept, try to make use of it wherever you find its possible use case.
Let me try and come up with a use case of first class functions:
def plusOne(number):
return number+1
def plusTwo(number):
return number+2
def listModifier(li, func):
result = []
for element in li:
result.append(func(element))
return result
# executing listModifier
print(listModifier([1,2,3,4], plusOne))
# prints out ---> [2,3,4,5]
In the above snippet, I passed a function (plusOne
) as the parameter to another function (listModifier
). Then, I made a call to plusOne
from within the listModifier
function. This would trigger the plusOne
function and will increment each value of list passed and then append it to a result
list. Finally, after the above operation, simply returned result
.
Now, let's suppose for some reason, the client comes to me and tells me that instead of incrementing each value of the element by 1, do it by 2, all I would have to do is simply replace the plusOne
parameter of listModifier
to plusTwo
like so:
print(listModifier([1,2,3,4], plusTwo)) # pretty neat eh?
# prints out ---> [3,4,5,6]
What Next
Let me tell you that, you have reached a major milestone by learning this concept. First Class Function form the basis of several other design patterns and concepts such as Closures and Decorators. You'd have a better understanding of those topics by having a knowledge of first class functions beforehand.
Would You Like to Support Me?
If you want to support me and my contents, then go ahead and consider doing it. I would highly appreciate that:
- YouTube Channel: Home to all sorts of peculiar tutos.
- GitHub: Looking forward to your PR 😉
Top comments (0)