说我有这两个功能:
def s(x,y,z):
if x <= 0:
return y
return z
def f(a,b):
return s(b, a+1, f(a,b-1)+1)
如果我想在脑海中找到f(5,2)
,它将像这样:
f(5,2) = s(2,6,f(5,1)+1)
f(5,1) = s(1,6,f(5,0)+1)
f(5,0) = s(0,6,f(5,-1)+1) = 6
f(5,1) = 7
f(5,2) = 8
我从不评估f(5,-1)
,因为不需要它。 s
函数将返回6,因为参数x
为零,因此不需要对参数z
进行求值。
但是,如果我尝试在python中运行它,它将一直循环递归,或者直到我得到最大递归深度错误为止,这大概是因为python想在执行s
函数之前评估所有参数。
我的问题是,如何以不再需要递归的方式实现这些功能或任何类似方案?是否可以将每个参数的求值时间推迟到函数中使用?
答案 0 :(得分:4)
您的思想正在与s()
的工作原理有关的“内幕知识”。 Python不能,因此它只能遵循严格的规则,即在进行调用之前必须对调用的所有参数表达式进行求值。
Python是一种高度动态的语言,在执行的每个步骤中,s
和f
都可以反弹以指向另一个对象。这意味着Python无法优化递归或内联函数逻辑。它无法将if x <= 0
的测试s()
取消以避免避免首先评估z
的值。
如果您作为程序员知道在某些情况下需要避免使用第三种表达式,则需要自己进行此优化。手动将s
中的逻辑合并到f
中:
def f(a, b):
if b <= 0:
return a + 1
return f(a, b - 1) + 1
或通过传入一个可调用的变量并使s()
负责对第三表达式的求值,直到s
确定是否需要计算它为止。
def s(x, y, z):
if x <= 0:
return y
return z() # evaluate the value for z late
def f(a, b):
# make the third argument a function so it is not evaluated until called
return s(b, a+1, lambda: f(a, b - 1) + 1)
答案 1 :(得分:3)
调用函数时,所有参数在传递给函数之前都经过充分评估。换句话说,f(5,-1)
甚至在s
开始之前就被执行。
幸运的是,有一种简单的方法可以按需评估表达式:函数。与其将f(a,b-1)
的结果传递给z
,而是将其传递给计算结果的 function :
def s(x,y,z):
if x <= 0:
return y
return z() # z is a function now
def f(a,b):
return s(b, a+1, lambda:f(a,b-1)+1)
print(f(5,2)) # output: 8