Introduction to Python code reading collection: Why not recommend Python beginners to look directly at the project source code
The code read in this article implements the construction of composite functions that call input functions in turn.
The code snippet read in this article comes from 30-seconds-of-python.
compose
from functools import reduce def compose(*fns): return reduce(lambda f, g: lambda *args: f(g(*args)), fns) # EXAMPLES add5 = lambda x: x + 5 multiply = lambda x, y: x * y multiply_and_add_5 = compose(add5, multiply) multiply_and_add_5(5, 2) # 15
The compose function receives multiple functions and returns the combined functions that call these functions in turn from right to left. Among the received functions, only the rightmost function (the first called function in the composite function) can receive more than one parameter, and other functions can only receive one parameter.
The function uses reduce to apply a lambda expression to the received function list fns in turn. A lambda expression that receives two parameters in reduce returns a new anonymous function (lambda expression). Through the iteration of the reduce function, all the functions in fns will be called in turn and combined into one function. Assuming that fns is (a,b,c,d,e), the composite function returned by the reduce function is a (b (C (d (E (* ARG)))
Let's go deep into the implementation of the compose function
The function compose(*fns) receives any number of parameters, all of which are contained in a tuple named fns.
>>> def fun(*arg): ... print(arg) ... print(type(arg)) ... >>> fun(1,2,3) (1, 2, 3) <class 'tuple'>
functools.reduce(function, iterable[, initializer]) applies the function of the two parameters cumulatively from left to right to the entry of iterable, so as to reduce the iteratable object to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) is the value calculated (((1 + 2) + 3) + 4) + 5). The parameter x on the left is the accumulated value, while the parameter Y on the right is the updated value from iterable.
The anonymous function lambda f, g: lambda *args: f(g(*args)) of reduce in the compose function can be written as follows:
def function1(f,g): def function2(*args): return f(g(*args)) return function2
Assuming that fns is (a,b,c,d,e), the cumulative call of the reduce function is function1 constructor function2. a. B first constructs a function function2 whose operation content is a(b(*arg)) as the input parameter of function1. Function2 and C constructed in this iteration call function1 function as input parameters for the second iteration. function1(function2,c) will construct a function whose operation content is function2(c(*arg)), unlock function2 of the previous iteration, and the operation content of the new function is a(b(c(*arg))). Iterating in this order, the actual operation content of the finally obtained function is a (b (C (d (E (* ARG))).
>>> from functools import reduce >>> def function1(f,g): ... def function2(*args): ... return f(g(*args)) ... return function2 ... >>> def a(arg): ... return 'a'+arg ... >>> def b(arg): ... return 'b'+arg ... >>> def c(arg): ... return 'c'+arg ... >>> def d(arg): ... return 'd'+arg ... >>> def e(arg): ... return 'e'+arg ... >>> f = reduce(function1, (a,b,c,d,e)) >>> print(f('f')) abcdef
compose_right
Based on the same principle as the compose function above, you can construct a composite function called from left to right in the opposite direction by exchanging the call order in the reduce function.
from functools import reduce def compose_right(*fns): return reduce(lambda f, g: lambda *args: g(f(*args)), fns) # EXAMPLES add = lambda x, y: x + y square = lambda x: x * x add_and_square = compose_right(add,square) add_and_square(1, 2) # 9