我正在做一个练习,我要创建一个表示函数的类(写成lambda表达式)和几个涉及它们的方法。
我到目前为止写的是:
class Func():
def __init__(self, func, domain):
self.func = func
self.domain = domain
def __call__(self, x):
if self.domain(x):
return self.func(x)
return None
def compose(self, other):
comp_func= lambda x: self.func(other(x))
comp_dom= lambda x: other.domain(x) and self.domain(other(x))
return Func(comp_func, comp_dom)
def exp(self, k):
exp_func= self
for i in range(k-1):
exp_func = Func.compose(exp_func, self)
return exp_func
如上所示,函数exp自身构成k-1次函数。现在我要编写一个递归版本的所述函数,采用相同的参数" self"和" k"。 但是,我很难弄清楚它是如何工作的。在我写的原始exp中,我可以访问原始函数" self"在所有迭代中,但是在创建递归函数时,我无法访问原始函数,并且每次迭代只能访问最新的组合函数。因此,举例来说,如果我尝试用自己创作自我一定次数,我会得到:
f= x+3
f^2= x+6
(f^2)^2= x+12
所以我们跳过了函数x + 9。
我如何解决这个问题?有没有办法继续保留对原始函数的访问权限?
更新
def exp_rec(self, k):
if k==1:
return self
return Func.compose(Func.exp_rec(self, k-1), self)
答案 0 :(得分:3)
这是一项练习,所以我不会提供答案。
在递归中,你想做两件事:
确定并检查告诉您何时停止的“保护条件”;以及
确定并计算告诉您下一个值的“递归关系”。
考虑一个简单的因子函数:
def fact(n):
if n == 1:
return 1
return n * fact(n - 1)
在这个例子中,保护条件相当明显 - 这是唯一的条件语句!并且递归关系在return语句中。
对于你的练习,事情稍微不那么明显,因为目的是定义一个函数组合,而不是一个直的整数计算。但请考虑:
f = Func(lambda x: x + 3)
(这是你的例子。)你希望f.exp(1)与f相同,f.exp(2)为f(f(x))。那就在那里告诉你保护条件和复发关系:
保护条件是exp()仅适用于正数。这是因为exp(0)可能必须为不同的输入类型返回不同的东西(当f = Func(lambda s:s +'!')时,exp(0)返回什么?)。
因此测试exp(1),并让该条件成为原始lambda。
然后,当递归地定义exp(n + 1)时,让它成为原始 lambda与exp(n)的组合。
您需要考虑以下几点:首先,您的类实例具有与之关联的数据。该数据将在您的递归中“随身携带”,因此您不必递归传递这么多参数。其次,您需要确定Func.exp()是否创建一个新的Func(),或者它是否修改现有的Func对象。最后,考虑如何编写一个硬编码函数Func.exp2()
,它只是构造了我们称之为Func.exp(2)
的函数。这应该可以让你了解你的复发关系。
<强>更新强>
基于一些评论,我觉得我应该展示这段代码。如果要使用递归函数修改self
对象,而不是返回一个新对象,则需要在修改之前“缓存”self
中的值,如下所示: / p>
func = self.func
domain = self.domain
... recursive function modifies self.func and self.domain