Python高级用法之【组成函数】(function composition)

function composition in Python

先了解python构造函数的动机,直观表示f(g(x))。在很多算法里面,需要直观的写出一些中间函数,然后把中间函数一个的输出给到另一个,这样就可以串联各中间函数。事实上,我们不需要看到中间函数的输出结果,而且也不希望代码冗余度很高。然后python就提供了这么一种手段。

先看代码:

def double(x):
    return x * 2

def inc(x):
    return x + 1

def compose_1(x):
    y = inc(x)
    return double(y)

def compose_2(f, g):
    return lambda x: f(g(x))

print(compose_1(20))
print(compose_2(double, inc)(20))

输出为:

42
42

我们可以用compose_1来表达函数串联使用,但compose_2提供的方法在多函数串联优势会大很多。 lambda x: f(g(x))表示的是匿名函数,想深入了解可以看我另一篇文章《python中的lambda关键字》。

对于多个函数的组合,可以用两种方法:

def double(x):
    return x * 2

def inc(x):
    return x + 1

def dec(x):
	return x - 1

def compose_2(f, g):
    return lambda x: f(g(x))

print(compose_2(compose_2(double, inc), dec)(20))

这种方法就是用一个一个串连起来,看起来也很臃肿。另一种就比较高级了:

import functools

def double(x):
    return x * 2

def inc(x):
    return x + 1

def dec(x):
    return x - 1

def compose_2(f, g):
    return lambda x: f(g(x))

def compose(*functions):
    return functools.reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x)

res = compose(double, inc, dec)
print(res(20))

想必大家很难理解下面这行是什么意思

functools.reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x)

没关系,我这篇文章的精髓就是来讲解这一行代码。首先,定义函数时用到的形参为" *function",在形参最前面有一个小星号(*)。对形参带星号的详细解释,请看我的另一篇文章《Python中星号(*)的用法》。其实只想理解星号在这里的用法,是没必要被其他文章带走的。这里的星号表示组合成元组(tuple),无论输入有几个,在咱这儿就是一个元组。这样一来compose就可以组合多个函数了,形参的输入则是多个函数名。

functool.reduce的功能可以查源代码了解,官方demo里给了一个解释,如下:

For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5).

有木有很熟悉。这里[1,2,3,4,5]对应上面的functions是一个函数名元组(后面接的lambda x:x让函数名有函数属性),函数之间的关系描述为f(g(x)),reduce函数只是用来表示函数的连接顺序。这里reduce所"reduce"的就是functions的长度。

参考:https://mathieularose.com/function-composition-in-python/

猜你喜欢

转载自blog.csdn.net/leviopku/article/details/82151602