Python代码阅读合集介绍:为什么不建议Python初学者直接阅读项目源码本文阅读的代码实现了调用组合函数的构造输入功能顺序。本文阅读的代码片段来自30-seconds-of-python。从functoolsimportreducedefcompose(*fns):returnreduce(lambdaf,g:lambda*args:f(g(*args)),fns)#EXAMPLESadd5=lambdax:x+5multiply=lambdax,y:x*ymultiply_and_add_5=compose(add5,multiply)multiply_and_add_5(5,2)#15compose函数接收多个函数,返回一个复合函数,从右到左依次调用这些函数。在接收函数中,只有最右边的函数(复合函数中第一个被调用的函数)可以接收多个参数,其他函数只能接收一个参数。该函数使用reduce依次将lambda表达式应用于接收到的函数列表fns。reduce中接收两个参数的lambda表达式返回一个新的匿名函数(lambda表达式)。通过reduce函数的迭代,依次调用fns中的所有函数,合并为一个函数。假设fns为(a,b,c,d,e),那么reduce函数返回的复合函数为a(b(c(d(e(*arg)))))接下来我们深入compose函数的实现函数compose(*fns)接受任意数量的参数,所有参数都包含在名为fns的元组中。>>>deffun(*arg):...print(arg)...print(type(arg))...>>>fun(1,2,3)(1,2,3)<类'tuple'>functools.reduce(function,iterable[,initializer])从左到右将两个参数的函数累加到iterable的项上,以将iterable对象减少为单个值。例如,reduce(lambdax,y:x+y,[1,2,3,4,5])计算((((1+2)+3)+4)+5)的值。左边的参数x是累加值,右边的参数y是可迭代的更新值。compose函数中reduce的匿名函数lambdaf,g:lambda*args:f(g(*args))可以这样写:deffunction1(f,g):deffunction2(*args):returnf(g(*args))returnfunction2假设fns为(a,b,c,d,e),reduce函数累计调用function1构造函数function2。首先将a和b作为function1的输入参数,构造函数function2,其运算内容为a(b(*arg))。本次迭代构造的function2和c作为入参,调用function1函数进行第二次迭代。function1(function2,c)会构造运算内容为function2(c(*arg))的函数,并解锁上一次迭代的function2,新函数的运算内容为a(b(c(*arg)))。如此迭代,最终得到的函数实际运算内容为a(b(c(d(e(*arg)))))。>>>fromfunctoolsimportreduce>>>deffunction1(f,g):...deffunction2(*args):...returnf(g(*args))...returnfunction2...>>>defa(arg):...return'a'+arg...>>>defb(arg):...return'b'+arg...>>>defc(arg):...return'c'+arg...>>>defd(arg):...return'd'+arg...>>>defe(arg):...return'e'+arg...>>>f=reduce(function1,(a,b,c,d,e))>>>print(f('f'))abcdefcompose_right和上面的compose函数原理一样,只需要reduce通过交换函数中的调用顺序,可以构造一个相反方向调用,从左到右调用的复合函数。fromfunctoolsimportreducedefcompose_right(*fns):returnreduce(lambdaf,g:lambda*args:g(f(*args)),fns)#示例add=lambdax,y:x+ysquare=lambdax:x*xadd_and_square=compose_right(add,square)add_and_square(1,2)#9
