#!/usr/bin/env python # coding: utf-8 # First-Class Functions # # [First-Class Function](https://developer.mozilla.org/en-US/docs/Glossary/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](https://en.wikipedia.org/wiki/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 # 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) # 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 # Now, the variable `make_cube` can be used as a function, like so: # In[12]: print(cube) print(make_cube(4)) # Functions can be passed as arguments and returned by other functions. # # A [higher-order function](https://en.wikipedia.org/wiki/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]) # `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) # 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]) # 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()) # 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}'.format(tag, text) return wrapper para_one = make_paragraph('p') print(para_one('This is a small paragraph.')) # returns '

This is a small paragraph.

' # 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!