如何将功能应用于自身?

时间:2018-03-06 18:37:16

标签: python

假设我有函数f,它接受​​一些变量并返回相同类型的变量。为简单起见,我们说

def f(x):
    return x/2+1

我有兴趣一遍又一遍地将f应用于自己。类似于f(f(f(...(f(x))...)))

我可以这样做

s = f(x)
for i in range(100):
    s = f(s)

但是我想知道是否有更简单,更简洁的方法来做同样的事情。我不想避免for循环(就像对自己的挑战一样)。是否有某种方法可以使用map或类似功能来实现这一目标?

7 个答案:

答案 0 :(得分:8)

  

是否有某种方法可以使用map或类似功能来实现此目的?

不是map,而是reduce。我不会将其用于此,但您可以在 n -item序列上调用reduce以使f被称为 n 次。例如:

>>> def f(x):
...   return x+1
... 
>>> reduce(lambda n,_: f(n), range(100), 42)
142

说明:

  • n被分配了每个连续的返回值f
  • _是来自range(100)的数字列表。这些数字都被忽略了。重要的是有多少。
  • 42是起始值。

100f(f(f...(f(42))...))的嵌套调用会产生142

答案 1 :(得分:4)

在Python中,for循环是最符合人体工程学和可读性的方法。所以我认为这主要是一种练习 - 在函数式语言中使用它们更为自然。

functools.reduce通过重复调用两个参数的函数将值列表折叠为单个值。这里的阶乘:

>>> import functools, operator
>>> operator.mul(2,3)
6
>>> functools.reduce(operator.mul, range(1, 10), 1)
362880

我们可以滥用它来仅为其长度使用值列表而忽略实际内容。

>>> def f(x):
...   return x/2+1
... 
>>> functools.reduce(lambda x, y: f(x), range(10), 1)
1.9990234375

或者我们可以将(一元)函数的 n 副本串在一起,并通过将每一个应用于累计值来折叠它们。

>>> import itertools
>>> functools.reduce(lambda x, g: g(x), itertools.repeat(f, 10), 1)
1.9990234375

答案 2 :(得分:2)

虽然从您的示例中不清楚您是否正在尝试计算最终数值结果或累积值列表,但您可以使用带有lambda函数的非常简单的递归方法:

单一值:

f = lambda x, c = 1:x if c == 100 else f(x/2 + 1, c+1)
>>f(200)
2

值列表:

f = lambda x, c = 1:x if c == 100 else f(x+[x[-1]/2+1], c+1)
>>f([200])
[200, 101, 51, 26, 14, 8, 5, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]

答案 3 :(得分:1)

构造将是递归。但递归要求您的调用堆栈在某个时刻结束。这种情况可以使用如下算法:

"documents/report.Rmd"

这通常是用于计算结果的方法,例如阶乘。

使用一个例子,添加一个需求(你只计算x< 2,只是作为例子):

"source_files/script1.R"

关键是调用堆栈开始返回(以避免溢出)

答案 4 :(得分:0)

您可以在定义的返回行中添加函数本身。一个例子是这里的最佳答案How can I build a recursive function in python?

答案 5 :(得分:0)

你可以分解出递归:

from functools import partial
recurse = partial(lambda g,f,x,n: g(g,f,x,n), # capture g
                  lambda g,f,x,n: n and g(g, f, f(x), n-1) or x)

如果你做的比单行更好,可以废除递归:

import itertools
def recurse(f, x, n):
  for _ in itertools.repeat(None, n):
    x = f(x)
  return x

然后:

>>> f = lambda x: x/2+1
>>> recurse(f, 42, 5)
7.0
>>> f(f(f(42)))
7.0

答案 6 :(得分:-1)

我认为你所询问的是名为递归的概念。你可以使用类似lambda函数的东西,但for循环中的递归调用本身并不坏。我一般会阅读有关递归函数的更多信息,然后专门查看python实现。