1

我是 Python 新手,正在学习函数。我遇到了以下功能,并在我的智慧中理解了它是如何工作的。在我看来,无论 的值如何b,答案都应该是 6,但事实并非如此。

代码

def mult(a, b):
    if b == 0:
        return 0
    rest = mult(a, b - 1)
    value = a + rest
    return value
print "3 * 2 = ", mult(3, 2)

我对发生的事情的理解

  1. 因为b不是 0 它继续
  2. rest被赋值3, 1并再次运行函数
  3. 因为b是 1 并且确实等于 0,所以它继续rest
  4. rest被赋值3, 0并再次运行函数
  5. 由于b现在为零,因此返回值 0
  6. 然后它继续进行,value其值为 3 + 3,a其值为 3,rest值为 3,即(3,0)
  7. 它返回值 6

但是如果我分配mult(3,4),它会返回值 12。根据我的理解,这是不可能的。显然,我不理解逻辑流程。我究竟做错了什么?

4

5 回答 5

4

这个函数的基本逻辑是:

让我们(a加减)直到1。像这样对你来说可能更有意义:bb == 0

def mult(a, b):
    value = 0
    while b > 0:
        b = b - 1
        value = value + a
    return value

只是代替了一个while循环,你的函数不断地调用自己。我设法联系到mult他自己,他愿意解释:

嗨,我的名字是 mult,我是 Recurser。递归器是计算机科学中的常见品种,我们有一个特殊功能;我们可以克隆自己。可悲的是,我被诅咒无法繁殖。尽管如此,我还是想实现我作为乘数的梦想,并且我确实设法找到了实现它的方法。就是这样:

当你要我繁殖(a, b)时,我会生成一个克隆并问他(a, b - 1)。克隆重复这个过程,直到产生一个被询问的克隆(a, 0)。当这种情况发生时(然后有一行我自己+b克隆),他回答产生他的克隆:0。那个克隆反过来又增加a了他刚刚被告知的内容(第一次是0 + a),并回答了他面前的克隆。这个过程一直重复,直到我得到自己生成的克隆的回答。我对此进行补充a,并将其作为最终答案返回给您!

def mult(a, b):
    # Should I ask a clone?
    if b == 0:
        # No! I reply 0 to my asker.
        return 0

    # Yes! I spawn a clone and ask him (a, b - 1) and wait for an answer to
    # store in 'rest'
    rest = mult(a, b - 1)

    # I take the answer and add to it the 'a' I was told
    value = a + rest

    # I return the value I calculated to my asker
    return value

print "3 * 2 = ", mult(3, 2)  # Here someone asks me (3, 2)
于 2012-12-04T01:06:52.690 回答
3

您可以检测您的代码,以便更轻松地查看正在发生的事情

def mult(a, b):
    print "mult(%s, %s)"%(a, b)
    if b == 0:
        return 0
    rest = mult(a, b - 1)
    value = a + rest
    print "returns %s"%value
    return value
print "3 * 2 = ", mult(3, 4)

3 * 2 =  mult(3, 4)
mult(3, 3)
mult(3, 2)
mult(3, 1)
mult(3, 0)
returns 3
returns 6
returns 9
returns 12
12

由于递归,打印语句是嵌套的

IE。mult(3, 0)返回 3,mult(3, 1)返回 6,依此类推

于 2012-12-04T01:06:11.253 回答
2
  1. mult()被调用3, 2(这是调用#1)

  2. 哪个调用mult()3, 1这是调用#2)

  3. 哪个调用mult()3, 0这是调用#3)

  4. 返回 0(因为b是零)来调用 #2

  5. call #2 现在返回 3 + 0 来调用 #1

  6. call #3 现在返回 3 + 3

基本上,每次调用都会将a值增加a,递归地深入研究 istelfb时间。因此,将 3 添加到自身 4 次将得到 12。

于 2012-12-04T01:06:08.057 回答
2

您的逻辑在第 5 条之前是正确的。然后在第 6 条您跳过了一些步骤。这是一个递归函数。通过在纸上绘制事件树更容易理解它,但让我们先恢复你的逻辑:

多(3,4):

 1. a = 3, b = 4
 1. rest = mult(3, 3)
 2. a = 3, b = 3
 2. rest = mult(3, 2)
 3. a = 3, b = 2
 3. rest = mult(3, 1)
 4. a = 3, b = 1
 4. rest = mult(3, 0)
 5. a = 3, b = 0
 5. return 0
 4. value = 3 + 0
 4. return 3
 3. value = 3 + 3
 3. return 6
 2. value = 3 + 6
 2. return 9
 1. value = 3 + 9
 1. return 12

在上面的示例中,行首的每个数字代表递归中的步骤。它从第 1 步开始,在这种情况下一直到第 5 步,然后以您的最终答案逐个返回,直到第 1 步。

该函数通过求和实现乘法的概念。例如,3 * 4 相当于将数字“4”加 3 次。

于 2012-12-04T01:08:43.543 回答
1

这是一种直观地查看递归如何工作的方法:

COUNTER = 0

def mult(a, b):
    global COUNTER

    COUNTER+=1
    print " "*COUNTER + "Called with", a,b

    if b == 0:
        return 0
    rest = mult(a, b - 1)
    value = a + rest

    COUNTER -= 1
    print " "*COUNTER, "Value:", value 

    return value

print "3 * 4 = "
print mult(3, 4)

输出

3 * 4 = 
 Called with 3 4
  Called with 3 3
   Called with 3 2
    Called with 3 1
     Called with 3 0
     Value: 3
    Value: 6
   Value: 9
  Value: 12
12

您可以看到调用堆栈是如何一直向下移动到底部 (b==0),然后将值返回到链的顶部。

于 2012-12-04T01:13:10.087 回答