One of the most powerful features of Python is that everything is an object, including functions. Functions in Python are first-class objects.
This broadly means, that functions in Python:
- have types
- can be sent as arguments to another function
- can be used in expression
- can become part of various data structures like dictionaries
Sending functions as arguments coupled with the ability to store them in lists can be extremely helpful. I know all of this can be hard to digest so let’s take this step by step.
Functions can be passed as arguments
For the rest of the tutorial, we will define an ‘apply’ function which will take as input a list, L and a function, f and apply the function to each element of the list. This example has been taken from the Edx Course 6.00.1.x.
Let’s see how we can call this function:
L = [1, -2, -5, 6.2]
print apply(L, abs) # [1, 2, 5, 6.2]
# abs is applied on elements passed in L
print apply(L, int) # [1, -2, -5, 6]
We can also pass a self-defined function. For example:
# Function to return square of a number
print apply(L,sqr) # [1, 4, 25, 38.440000000000005]
The ability to perform the same operation on a list of elements is also provided by a higher-order python function called map.
In its simplest form, it takes in a ‘unary’ function and a collection of suitable arguments and returns an ‘iterable’ which we must walk down.
So the above apply function could become:
for i in map(abs,[1, -2, -5, 6.2]):
To read more about the map operation, head over to: Python map
Functions as elements of a list
Functions can be stored as elements of a list or any other data structure in Python. For example, if we wish to perform multiple operations to a particular number, we define apply_func(L, x) that takes a list of functions, L and an operand, x and applies each function in L on x.
Now, to call this function:
function_list = [abs,exp,int]
print apply_func(function_list,-2.3) # [2.3, 0.10025884, -2]
# Functions in function_list are applied to -2.3
print apply_func(function_list,-4.6) # [4.6, 0.01005184, -4]
Side Note: In both the above examples, we could have used list comprehensions. List comprehensions in python provide an elegant way of creating lists based on another list or iterator. For example, lines 14-16 in apply_func could become:
output = [f(x) for f in L]
Functions can be assigned to other variables
An interesting point to note here is that we can assign different variables for these functions. This means, we can say:
i = abs
print(i(-2)) # 2
This is because functions operate exactly like objects and can be passed around. But, an idea that is even more powerful is that all objects can behave like functions as well.
Objects as functions
This part will require us to understand a little bit more about what makes an object a function. Objects can be treated as functions means that they can be called by using round paranthesis (), just like a function.
This can be done by defining a __call__ function inside the object. Let’s define a class that when called, prints whatever it stores.
s1 = Printer('Hello') # Defining object of class Printer
# Calling object s1
s1() # Hello
Thus, under the hood ‘calling’ an object means executing the object’s __call__ method.
- Functions in python are first class objects. This means that they can be passed as arguments to other functions, assigned to variables or even stored as elements in various data structures.
- The ability to perform the same operation on a list of elements is provided by a higher-order python function called map.
- Objects can be made callable by defining a __call__ function.
You can read more about this topic at:
If you wish to learn more about List Comprehensions, check this out: List Comprehensions in Python