First-Class Functions

First-Class Function: A programming language is said to have First-class functions when functions in that language are treated like any other variable. For example, in such a language, a function can be passed as an argument to other functions, can be returned by another function and can be assigned as a value to a variable.

First-Class Citizen: a first-class citizen (also type, object, entity, or value) in a given programming language is an entity which supports all the operations generally available to other entities. These operations typically include being passed as an argument, returned from a function, modified, and assigned to a variable.

We'll go through some examples to understand what first-class functions are. Note this notebook uses Python 3.6.0.

In [9]:
def cube(number: int) -> int:
    """ Return the cube of a number. """
    
    return number ** 3

cube_two = cube(2)    # Call the function, set cube_two to the value returned

print(cube)            # It says cube is a function
print(cube_two)       # The value stored in cube_two
<function cube at 0x05D8CE40>
8
In [10]:
nums = [4, cube(4), cube(4) / cube(4) ** 0.5]    # returned values as list elements
print(nums)

cube_dict = {'two_cubed': cube(2), 'five_cubed': cube(5)}   # as dict values
print(cube_dict)
[4, 64, 8.0]
{'two_cubed': 8, 'five_cubed': 125}

Now we'll see how we can set a variable to the cube() function.

In [11]:
make_cube = cube    # Take out those parentheses

print(cube)
print(make_cube)    # make_cube points to the cube() function
<function cube at 0x05D8CE40>
<function cube at 0x05D8CE40>

Now, the variable make_cube can be used as a function, like so:

In [12]:
print(cube)
print(make_cube(4))
<function cube at 0x05D8CE40>
64

Functions can be passed as arguments and returned by other functions.

A higher-order function accepts other functions as arguments or returns functions as its result.

map is an example: it takes a function and an iterable as its arguments, and it applies the function to each value of that iterable and then returns a new iterable of those results.

Here's an example of map taking a function (int) as an argument.

In [13]:
str_nums = ['1', '2', '3']
one, two, three = map(int, str_nums)  # similar to [int(n) for n in str_nums]

print(str_nums)
print([one, two, three])
['1', '2', '3']
[1, 2, 3]

reduce is another example: it applies a function of two arguments cumulatively to the items of an iterable. Let's look at an example to see what this means.

In [14]:
from functools import reduce

cumu_diff = reduce(lambda x, y: x - y, [3, 2, 1])    # cumulative difference
print(cumu_diff)
0

Let's create a map-like function (well, kind of).

In [15]:
from typing import Callable, Sequence, Iterable

def map_it(func: Callable, seq: Sequence) -> Iterable:
    """ Apply a given function to a sequence and yield the result. """
    for item in seq:
        yield func(item)

str_nums = ['1', '2', '3']
one, two, three = map_it(int, str_nums)    # same as map(int, str_nums)

print([one, two, three])
[1, 2, 3]

Now, let's see how to return a function from another function.

In [16]:
def greet(name: str) -> str:
    """ Return a callable function with the given name. """
    
    def print_message():
        """ A callable that prints a message to stdout. """
        print("Hello, {}!".format(name))
    
    return print_message                  # returning the function, not calling it

greet_et = greet('E.T.')                 # greet_et points to print_message()

print(greet)
print(greet_et)
print(greet_et())
<function greet at 0x05D8C858>
<function greet.<locals>.print_message at 0x05D8C270>
Hello, E.T.!
None

Here's another example.

In [17]:
def make_paragraph(tag: str) -> str:
    """ Return a callable function with the given tag. """
    
    def wrapper(text: str) -> str:
        """ Return text wrapped with a tag. """
        return '<{0}>{1}</{0}>'.format(tag, text)
    
    return wrapper


para_one = make_paragraph('p')

print(para_one('This is a small paragraph.'))   # returns '<p>This is a small paragraph.</p>'
<p>This is a small paragraph.</p>

In conclusoin, in Python, functions are first-class objects. You can pass functions around as arguments to other functions, store them as dictionary or list values, or have a function return another function.

We've seen several ways to use functions in Python. Happy programming!