首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >只有在必要时才计算Python递归

只有在必要时才计算Python递归
EN

Stack Overflow用户
提问于 2018-11-03 13:06:05
回答 2查看 110关注 0票数 3

假设我有以下两个功能:

代码语言:javascript
运行
复制
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),它会是这样的:

代码语言:javascript
运行
复制
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函数之前计算所有参数。

我的问题是,当不再需要递归时,我将如何实现这些函数或任何类似的场景?是否有可能将对每个论点的评估推迟到在函数中使用?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-11-03 13:17:26

你的头脑是与“内部人的知识”如何s()工作。Python不能这样做,因此它只能遵循严格的规则,即调用的所有参数表达式都必须在进行调用之前进行计算。

Python是一种高度动态的语言,在执行的每一步,sf都可以反弹到不同的对象。这意味着Python不能优化递归或内联函数逻辑。它不能将if x <= 0测试提升到s()之外,以避免首先评估z的值。

如果您作为程序员知道在某些情况下需要避免使用第三个表达式,那么您需要自己进行优化。要么将s中的逻辑手动合并到f中:

代码语言:javascript
运行
复制
def f(a, b):
    if b <= 0:
        return a + 1
    return f(a, b - 1) + 1

或者将第三个表达式的计算推迟到s()确定是否需要计算时,方法是传入一个可调用的,并让s负责计算它:

代码语言:javascript
运行
复制
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)
票数 4
EN

Stack Overflow用户

发布于 2018-11-03 13:15:35

当一个函数被调用时,所有的参数在传递给函数之前都会被完全计算。换句话说,f(5,-1)甚至在s启动之前就已经被执行了。

幸运的是,有一种按需计算表达式的简单方法:函数。与其将f(a,b-1)的结果传递给z,不如传递给它一个计算结果的函数:

代码语言:javascript
运行
复制
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
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53131620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档