Eulclid的算法:递归结束时,Python代码返回None

时间:2019-09-25 04:47:41

标签: python-3.x algorithm

我正在尝试使用递归实现Euclid's algorithm for computing the greatest common divisor。下面是相同的代码。

def euclid(a,b):
    if a>b:
        r=a%b
        if (r == 0):
            return b
        else:
            a=b
            b=r
            euclid(a,b)

print(euclid(20,4)) # Returns 4
print(euclid(20,8)) # Returns None

对于第一个数据集,我得到了正确的结果。但是对于euclid(20,8),我得到了None的回报。

在调试器中进行检查时,确实看到了b的返回值变为4,但是由于某种原因,我的代码跳到了euclid(a,b)并返回了None

这里的主要收获是要理解为什么代码不返回4而是跳转到euclid(a,b)并返回None的原因。

请避免提供其他代码解决方案,但我们非常鼓励您指出当前代码行为的原因。

3 个答案:

答案 0 :(得分:1)

您实际上并没有在else路径中返回 任何东西,因此它只是假设您最了解并为您返回None

您为4获得print(euclid(20,4))的唯一原因是因为420的因数,所以请不要使用 {{1} }路径。而是立即返回else。对于其他任何事情,从第一次递归调用b返回的东西将始终为euclid()(即使对该函数的较低调用返回了某些内容,您也从第一次调用返回时将其丢弃了)。

您需要None而不是return euclid(a,b)


顺便说一句(这不是回答您的特定问题所必需的,但是它对改进代码的实现有很大帮助),我不是euclid(a,b)构造的忠实拥护者,因为{ {1}}是完全多余的(如果未返回,则if something then return else …位是自动的)。

此外,当您只需更改传递到下一个递归级别的内容时,就不需要分配变量。

考虑到这两个因素(并简化了很多步骤),您可以执行以下操作:

else

答案 1 :(得分:1)

该代码有时会返回None的原因是,在控制流中,您最终会遇到没有return语句的情况,例如您的第一个a <= b中的if或第二个r != 0中的if时。在这种情况下,Python的默认行为是返回None,因为您似乎已经发现了困难的方法。

def euclid(a,b):
    if a>b:
        r=a%b
        if (r == 0):
            return b
        else: # <--- no `return` in this branch!
            a=b
            b=r
            euclid(a,b)
    # else:  # <--- no `return` in this branch!
    #     ...   

这是您代码的更新版本,可以解决该问题以及许多其他问题:

  • 该函数的名称应该有意义:https://www.dropbox.com/s/5inunjyj9jx8w0i/WMR%20Issue.mp4?dl=0很受欢迎,并且有一堆以他命名的东西,最好指定您实际要计算Euclid
  • 实际上并不需要第一个if,因为随后的代码会处理它:计算r,而递归调用将交换a和{{1 }},如果是b,如果是a < b,那么是a == b,那么您将直接返回r == 0
  • ba = b毫无用处,请不要使用它们,只需让您的递归调用直接使用b = rb
  • 第二个r可以用一行写得更清楚
if

答案 2 :(得分:0)

您的代码存在缩进错误,并且代码中缺少一个路径(r!= 0)。应该是

def euclid(a,b):
    if a>=b:
        r=a%b
        if (r == 0):
            return b
        return euclid(b, r)
    else:
        return euclid(b, a)