Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:编写函数的n个组合的更好方法?_Python_Function_Composition - Fatal编程技术网

Python:编写函数的n个组合的更好方法?

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))."""

我写了一个函数“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 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中,迭代通常更自然。直到今天早上我才学会递归。我没有研究你的解决方案,因为我不想破坏自己的任何东西。我用递归的方法回答了我最初的问题,它看起来几乎和你的一样!谢谢