Python:编写函数的n个组合的更好方法?
我写了一个函数“rep”,它接受一个函数f,并接受f的n个组合。 所以rep(square,3)的行为如下:square(square(square(x)))。 当我将3传递给它时,rep(square,3)(3)=6561 我的代码没有问题,但我想知道是否有一种方法可以使它“更漂亮”(或更短),而不必调用另一个函数或导入任何内容。谢谢Python:编写函数的n个组合的更好方法?,python,function,composition,Python,Function,Composition,我写了一个函数“rep”,它接受一个函数f,并接受f的n个组合。 所以rep(square,3)的行为如下:square(square(square(x)))。 当我将3传递给它时,rep(square,3)(3)=6561 我的代码没有问题,但我想知道是否有一种方法可以使它“更漂亮”(或更短),而不必调用另一个函数或导入任何内容。谢谢 def compose1(f, g): """Return a function h, such that h(x) = f(g(x))."""
def compose1(f, g):
"""Return a function h, such that h(x) = f(g(x))."""
def h(x):
return f(g(x))
return h
def rep(f,n):
newfunc = f
count=1
while count < n:
newfunc = compose1(f,newfunc)
count+=1
return newfunc
def组件1(f,g):
“”“返回函数h,使h(x)=f(g(x))。”“”
def h(x):
返回f(g(x))
返回h
def代表(f,n):
newfunc=f
计数=1
当计数
为循环使用
而不是,而
更短,可读性更高,compose1
实际上不需要是一个单独的函数。虽然我同意相同函数的重复组合最好用循环完成,但您可以使用*args
组合任意数量的函数:
def identity(x):
return x
def compose(*funcs):
if funcs:
rest = compose(*funcs[1:])
return lambda x: funcs[0](rest(x))
else:
return identity
在这种情况下,您会:
def rep(f,n):
funcs = (f,)*n # tuple with f repeated n times
return compose(*funcs)
正如DSM在评论中善意地指出的,您可以像这样删除递归:
def compose(*funcs):
if not funcs:
return identity
else:
def composed(x):
for f in reversed(funcs):
x = f(x)
return x
return composed
(还请注意,如果您还想支持正在编写的函数的任意参数,可以将x
替换为*args
,但我只保留了一个参数,因为这就是原始问题中的情况)如果您想要提高速度,那么for
循环显然是一个不错的选择。但如果你在寻找理论上的学术认可;-),坚持使用简洁的功能性成语。比如:
def rep(f, n):
return f if n == 1 else lambda x: f(rep(f, n-1)(x))
也许有人会发现这个解决方案很有用
组合函数数
from functools import reduce
def compose(*functions):
return reduce(lambda x, y: (lambda arg: x(y(arg))), functions)
def multi(how_many, func):
return compose(*[func for num in range(how_many)])
使用列表理解生成函数列表
from functools import reduce
def compose(*functions):
return reduce(lambda x, y: (lambda arg: x(y(arg))), functions)
def multi(how_many, func):
return compose(*[func for num in range(how_many)])
用法
这种方法还有另一个优点:它将处理rep(lambda x:x**2,10**4)(1.0)
,而由于Python的递归限制,原始方法不会。您可以将这些想法结合起来:您可以在返回的h
中反向循环funcs
。好的,逐步完成它。假设n
为2。然后rep(f,2)
返回lambda x:f(rep(f,1)(x))
。如果你打开它,比如说,8.4
,它就变成了f(rep(f,1)(8.4))
。rep(f,1)
部分返回f
,这就是f(f(8.4))
。现在,您可以自己尝试一个n
3;-)一般来说,只要看到迭代,就可以使用递归,反之亦然。在函数式语言中,递归通常更自然;在Python中,迭代通常更自然。直到今天早上我才学会递归。我没有研究你的解决方案,因为我不想破坏自己的任何东西。我用递归的方法回答了我最初的问题,它看起来几乎和你的一样!谢谢