Miscellany¶
First Class Functions¶
Functions are first class values in Python, and are objects just like anything else. The can be passed as arguments, stored in variables, and applied later zero, 1, or more times. As an example, here is a unit test in the code to demonstrate.
“test_first_class_functions” is a function that is run by pytest, a unit test framework [1].
24def test_first_class_functions():
25 def doubler(x: int) -> int:
26 return x * 2
27
28 def add_five_to_result_of(f: typing.Callable[[int], int], x: int) -> int:
29 return 5 + f(x)
30
31 assert 11 == add_five_to_result_of(doubler, 3)
32 assert 13 == add_five_to_result_of(doubler, 4)
Inside of the body of test_first_class_functions, we define a function named “doubler”. “doubler” take an integer as input, named “x”, and returns an integer. Within the body of “doubler”, the input “x” is multiplied by 2, the result of which is the return value.
“doubler” is a function that is only available within the scope of “test_firstclassfunctions”.
“add_five_to_result_of” is another local function. It takes two parameters, “f” and “x”.
The parameter f is a function that takes an int as a parameter, and returns an int. “f: typing.Callable[[int], int]” means that f can be treated as a function that can be called, where there is only one parameter to f, of type int, and the result of calling f is of type int
The parameter x is an int
If you are unfamiliar with looking at the lines above, it’s a session in the Python Read-Evaluate-Print loop, read more here.
As a harder example, if Python didn’t have recursion, but it does have first class functions as values, the programmer could simulate recursion by passing a function to itself as a parameter.
37def test_factorial_no_recursion():
38 def factorial(n: int, f: typing.Callable[[int], int]) -> int:
39 if n == 1:
40 return 1
41 else:
42 return n * f(n - 1, f)
43
44 assert 1 == factorial(1, factorial)
45 assert 2 == factorial(2, factorial)
46 assert 6 == factorial(3, factorial)
47 assert 24 == factorial(4, factorial)