假设我有以下两个功能:
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
函数之前计算所有参数。
我的问题是,当不再需要递归时,我将如何实现这些函数或任何类似的场景?是否有可能将对每个论点的评估推迟到在函数中使用?
发布于 2018-11-03 13:17:26
你的头脑是与“内部人的知识”如何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)
发布于 2018-11-03 13:15:35
当一个函数被调用时,所有的参数在传递给函数之前都会被完全计算。换句话说,f(5,-1)
甚至在s
启动之前就已经被执行了。
幸运的是,有一种按需计算表达式的简单方法:函数。与其将f(a,b-1)
的结果传递给z
,不如传递给它一个计算结果的函数:
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
https://stackoverflow.com/questions/53131620
复制相似问题