涉及函数、递归和类的Python练习
我正在做一个练习,其中我将创建一个表示函数(编写为lambda表达式)的类,以及一些涉及函数的方法 到目前为止,我写的是:涉及函数、递归和类的Python练习,python,oop,recursion,Python,Oop,Recursion,我正在做一个练习,其中我将创建一个表示函数(编写为lambda表达式)的类,以及一些涉及函数的方法 到目前为止,我写的是: class Func(): def __init__(self, func, domain): self.func = func self.domain = domain def __call__(self, x): if self.domain(x): return self.fun
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”,但是,在生成递归函数时,我失去了对原始函数的访问权,并且每次迭代都只能访问最近合成的函数。例如,如果我试着用self创作self,我会得到:
f= x+3
f^2= x+6
(f^2)^2= x+12
所以我们跳过了函数x+9
我该怎么做?是否有办法保留对原始功能的访问权限
更新:
这是一个练习,所以我不提供答案 在递归中,您需要做两件事:
- 确定并检查“防护条件”,告知您何时停止;及
- 确定并计算告诉您下一个值的“递归关系”
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
中的值之前“缓存”,如下所示:
func = self.func
domain = self.domain
... recursive function modifies self.func and self.domain
IMHO如果您必须将lambda分配给变量,那么最好从中创建一个闭包(即使用
def funcname(x):
而不是funcname=lambda x:…
说明说明我将使用lambda表达式。好吧,那么请记住:谢谢你的回答。但是这并不能真正让我知道如何前进,因为正如你所说,我应该让exp(n+1)是原始lambda函数的组合,但如何访问“原始”函数?exp可以接受的唯一参数是“self”和“k”显然,我没有得到关于原始函数的任何信息,因此递归必须接受原始函数的某些版本。因此,在第一次迭代之后,exp将不再记得原始lambda函数,而只记得直到某个k的组合。那么我如何组合exp(n)使用它?self不是在它里面的某个地方有函数吗?一开始。但只有在递归的第一步中。在第一步中,你用self组合self,创建self^2。然后你将它传递到递归的下一步,因此self现在是self^2。如果你再次尝试用self组合它,你会得到self^4而不是self^3。这是假设的您已经决定exp()
修改self(而不是返回单独的对象)。在这种情况下,在递归之前,将lambda函数存储在局部变量中。[编辑]我为演示添加了一个更新。我不希望修改原始自我。但我不能将同一个自我传递到递归的下一步,否则我不会真正做任何事情。当我在exp中调用exp时,我必须在合成版本的自我上调用它。然后在下一步,exp不知道原始自我是什么。
func = self.func
domain = self.domain
... recursive function modifies self.func and self.domain