Python 向递归斐波那契程序添加功能时遇到问题

Python 向递归斐波那契程序添加功能时遇到问题,python,recursion,fibonacci,Python,Recursion,Fibonacci,我正在使用一个基本的Python MIT免费课件,我遇到了一个递归练习的问题。原始程序接受一个整数,并使用递归提供其斐波那契函数。本书提供了该程序的脚本,但随后的练习要求输入一种方法,使程序能够识别在计算fib(n)的过程中执行了多少次fib(2)。我希望能得到一些帮助,因为我已经被困在这个问题上一个星期了 代码如下: def fib(n): """Assumes n is int > 0 Returns Fibonacci Number of n""" if n

我正在使用一个基本的Python MIT免费课件,我遇到了一个递归练习的问题。原始程序接受一个整数,并使用递归提供其斐波那契函数。本书提供了该程序的脚本,但随后的练习要求输入一种方法,使程序能够识别在计算
fib(n)
的过程中执行了多少次
fib(2)
。我希望能得到一些帮助,因为我已经被困在这个问题上一个星期了

代码如下:

def fib(n):
    """Assumes n is int > 0
    Returns Fibonacci Number of n"""
    if n ==0 or n==1:
        return n        
    else:
        return fib(n-1) + fib(n-2)

def testfib(n):
    for i in range(n+1):
        print('fib of', i, 'is ', fib(i))

x=int(input('Enter a number: '))

print('Fibonacci of', x, 'is',fib(x))
print(testfib(x))

参考资料:使用Python进行计算和编程的介绍,图4.7可能有点过火,但是将整个内容包装到一个类中,您可以很容易地引入计数器。这里首先创建一个名为Fib的可调用
Fib
对象。当您现在调用
fib(x)
时,在
\uuuuuuuuuuuuu
函数中将计数器设置为零,然后调用执行实际工作的
fib.fib
函数。在
Fib.Fib
函数中,每当函数参数等于2时,计数器将增加1

class Fib:
    def __init__(self):
        self.count = 0

    def __call__(self, n):
        self.count = 0
        return self.fib(n)

    def fib(self,n):
        """Assumes n is int > 0
        Returns Fibonacci Number of n"""
        if n == 2:
            self.count += 1

        if n ==0 or n==1:
            return n        
        else:
            return self.fib(n-1) + self.fib(n-2)



fib = Fib()
x=5

print('Fibonacci of', x, 'is',fib(x))
print('fib(2) was called {} times'.format(fib.count))
对于示例参数(
x=5
),输出为:

Fibonacci of 5 is 5
fib(2) was called 3 times
Enter a number: 7
Fibonacci of 7 is 13
fib of 0 is  0  count of fib(2) is  0
fib of 1 is  1  count of fib(2) is  0
fib of 2 is  1  count of fib(2) is  1
fib of 3 is  2  count of fib(2) is  1
fib of 4 is  3  count of fib(2) is  2
fib of 5 is  5  count of fib(2) is  3
fib of 6 is  8  count of fib(2) is  5
fib of 7 is  13 count of fib(2) is  8
None

也许有点过火,但是将整个内容包装到一个类中,您可以很容易地引入计数器。这里首先创建一个名为Fib的可调用
Fib
对象。当您现在调用
fib(x)
时,在
\uuuuuuuuuuuuu
函数中将计数器设置为零,然后调用执行实际工作的
fib.fib
函数。在
Fib.Fib
函数中,每当函数参数等于2时,计数器将增加1

class Fib:
    def __init__(self):
        self.count = 0

    def __call__(self, n):
        self.count = 0
        return self.fib(n)

    def fib(self,n):
        """Assumes n is int > 0
        Returns Fibonacci Number of n"""
        if n == 2:
            self.count += 1

        if n ==0 or n==1:
            return n        
        else:
            return self.fib(n-1) + self.fib(n-2)



fib = Fib()
x=5

print('Fibonacci of', x, 'is',fib(x))
print('fib(2) was called {} times'.format(fib.count))
对于示例参数(
x=5
),输出为:

Fibonacci of 5 is 5
fib(2) was called 3 times
Enter a number: 7
Fibonacci of 7 is 13
fib of 0 is  0  count of fib(2) is  0
fib of 1 is  1  count of fib(2) is  0
fib of 2 is  1  count of fib(2) is  1
fib of 3 is  2  count of fib(2) is  1
fib of 4 is  3  count of fib(2) is  2
fib of 5 is  5  count of fib(2) is  3
fib of 6 is  8  count of fib(2) is  5
fib of 7 is  13 count of fib(2) is  8
None

有更简洁的方法可以做到这一点,但最简单的方法是使用全局变量来记录arg为2调用
fib
时的计数。不过,您需要记住在每次最外面的呼叫之前重置计数器

count = 0

def fib(n):
    """Assumes n is int > 0
    Returns Fibonacci Number of n"""
    global count
    if n == 0 or n == 1:
        return n
    else:
        if n == 2:
            count += 1
        return fib(n-1) + fib(n-2)

def testfib(n):
    global count
    for i in range(n+1):
        count = 0
        print('fib of', i, 'is ', fib(i), ', called fib(2)', count, 'times')

x=int(input('Enter a number: '))

count = 0
print('Fibonacci of', x, 'is', fib(x), ', called fib(2)', count, 'times')
testfib(x)
演示

Enter a number: 7
Fibonacci of 7 is 13 , called fib(2) 8 times
fib of 0 is  0 , called fib(2) 0 times
fib of 1 is  1 , called fib(2) 0 times
fib of 2 is  1 , called fib(2) 1 times
fib of 3 is  2 , called fib(2) 1 times
fib of 4 is  3 , called fib(2) 2 times
fib of 5 is  5 , called fib(2) 3 times
fib of 6 is  8 , called fib(2) 5 times
fib of 7 is  13 , called fib(2) 8 times

更好的方法是使用函数属性,而不是可修改的全局属性

def fib(n):
    """Assumes n is int > 0
    Returns Fibonacci Number of n"""
    if n == 0 or n == 1:
        return n
    else:
        if n == 2:
            fib.count += 1
        return fib(n-1) + fib(n-2)

def testfib(n):
    for i in range(n+1):
        fib.count = 0
        print('fib of', i, 'is ', fib(i), ', called fib(2)', fib.count, 'times')

x=int(input('Enter a number: '))

fib.count = 0
print('Fibonacci of', x, 'is', fib(x), ', called fib(2)', fib.count, 'times')
testfib(x)

有更简洁的方法可以做到这一点,但最简单的方法是使用全局变量来记录arg为2调用
fib
时的计数。不过,您需要记住在每次最外面的呼叫之前重置计数器

count = 0

def fib(n):
    """Assumes n is int > 0
    Returns Fibonacci Number of n"""
    global count
    if n == 0 or n == 1:
        return n
    else:
        if n == 2:
            count += 1
        return fib(n-1) + fib(n-2)

def testfib(n):
    global count
    for i in range(n+1):
        count = 0
        print('fib of', i, 'is ', fib(i), ', called fib(2)', count, 'times')

x=int(input('Enter a number: '))

count = 0
print('Fibonacci of', x, 'is', fib(x), ', called fib(2)', count, 'times')
testfib(x)
演示

Enter a number: 7
Fibonacci of 7 is 13 , called fib(2) 8 times
fib of 0 is  0 , called fib(2) 0 times
fib of 1 is  1 , called fib(2) 0 times
fib of 2 is  1 , called fib(2) 1 times
fib of 3 is  2 , called fib(2) 1 times
fib of 4 is  3 , called fib(2) 2 times
fib of 5 is  5 , called fib(2) 3 times
fib of 6 is  8 , called fib(2) 5 times
fib of 7 is  13 , called fib(2) 8 times

更好的方法是使用函数属性,而不是可修改的全局属性

def fib(n):
    """Assumes n is int > 0
    Returns Fibonacci Number of n"""
    if n == 0 or n == 1:
        return n
    else:
        if n == 2:
            fib.count += 1
        return fib(n-1) + fib(n-2)

def testfib(n):
    for i in range(n+1):
        fib.count = 0
        print('fib of', i, 'is ', fib(i), ', called fib(2)', fib.count, 'times')

x=int(input('Enter a number: '))

fib.count = 0
print('Fibonacci of', x, 'is', fib(x), ', called fib(2)', fib.count, 'times')
testfib(x)
功能属性 这利用了Python的一个鲜为人知的特性,该特性由创建,以避免全局变量或创建完整的类。Python函数可以有自己的属性,这些属性可以用来提供与某些其他语言中的静态变量相同的功能。因此,在代码中可以执行以下操作:

def fib(n):
    """Assumes n is int > 0
    Returns Fibonacci Number of n"""
    if n == 2:
        try:
            fib.two_count += 1
        except AttributeError:
            fib.two_count = 1
    if n ==0 or n==1:
        return n        
    else:
        return fib(n-1) + fib(n-2)

def testfib(n):
    for i in range(n+1):
        fib.two_count = 0
        print(
            'fib of', i, 'is ', fib(i),
            'and fib(2) was called', fib.two_count, 'times'
        )

x=int(input('Enter a number: '))

print('Fibonacci of', x, 'is',fib(x))
print(testfib(x))
功能属性 这利用了Python的一个鲜为人知的特性,该特性由创建,以避免全局变量或创建完整的类。Python函数可以有自己的属性,这些属性可以用来提供与某些其他语言中的静态变量相同的功能。因此,在代码中可以执行以下操作:

def fib(n):
    """Assumes n is int > 0
    Returns Fibonacci Number of n"""
    if n == 2:
        try:
            fib.two_count += 1
        except AttributeError:
            fib.two_count = 1
    if n ==0 or n==1:
        return n        
    else:
        return fib(n-1) + fib(n-2)

def testfib(n):
    for i in range(n+1):
        fib.two_count = 0
        print(
            'fib of', i, 'is ', fib(i),
            'and fib(2) was called', fib.two_count, 'times'
        )

x=int(input('Enter a number: '))

print('Fibonacci of', x, 'is',fib(x))
print(testfib(x))

将计数器包含在函数本身中,并让它返回两个值(斐波那契值和计数)。这使您无需手动执行重置计数的业务逻辑。您可以根据需要多次调用该函数,并且计数将是正确的,而不是每次调用
fib
时的计数总和

def fib(n):
    """Assumes n is int > 0
    Returns the nth Fibonacci number and number of times it was called"""
    if n == 0 or n == 1:
        return n, 0
    else:
        f1, count1 = fib(n-1)
        f2, count2 = fib(n-2)
        sum_counts = count1 + count2
        if n == 2:
            sum_counts = 1
        return f1 + f2, sum_counts


def testfib(n):
    for i in range(n+1):
        f, count = fib(i)
        print('fib of', i, 'is ', f, end="\t")
        print('count of fib(2) is ', count)

x = int(input('Enter a number: '))

print('Fibonacci of', x, 'is', fib(x)[0])
print(testfib(x))
输出为:

Fibonacci of 5 is 5
fib(2) was called 3 times
Enter a number: 7
Fibonacci of 7 is 13
fib of 0 is  0  count of fib(2) is  0
fib of 1 is  1  count of fib(2) is  0
fib of 2 is  1  count of fib(2) is  1
fib of 3 is  2  count of fib(2) is  1
fib of 4 is  3  count of fib(2) is  2
fib of 5 is  5  count of fib(2) is  3
fib of 6 is  8  count of fib(2) is  5
fib of 7 is  13 count of fib(2) is  8
None

由于问题对
n==2
情况的处理方式不同,因此可以在递归中使用另一个基本情况

def fib(n):
    """Assumes n is int > 0
    Returns Fibonacci Number of n and number fo times it was called"""
    if n == 0 or n == 1:
        return n, 0
    elif n == 2:
        return (fib(0) + fib(1)), 1
    else:
        f1, count1 = fib(n-1)
        f2, count2 = fib(n-2)
        return f1 + f2, count1 + count2

将计数器包含在函数本身中,并让它返回两个值(斐波那契值和计数)。这使您无需手动执行重置计数的业务逻辑。您可以根据需要多次调用该函数,并且计数将是正确的,而不是每次调用
fib
时的计数总和

def fib(n):
    """Assumes n is int > 0
    Returns the nth Fibonacci number and number of times it was called"""
    if n == 0 or n == 1:
        return n, 0
    else:
        f1, count1 = fib(n-1)
        f2, count2 = fib(n-2)
        sum_counts = count1 + count2
        if n == 2:
            sum_counts = 1
        return f1 + f2, sum_counts


def testfib(n):
    for i in range(n+1):
        f, count = fib(i)
        print('fib of', i, 'is ', f, end="\t")
        print('count of fib(2) is ', count)

x = int(input('Enter a number: '))

print('Fibonacci of', x, 'is', fib(x)[0])
print(testfib(x))
输出为:

Fibonacci of 5 is 5
fib(2) was called 3 times
Enter a number: 7
Fibonacci of 7 is 13
fib of 0 is  0  count of fib(2) is  0
fib of 1 is  1  count of fib(2) is  0
fib of 2 is  1  count of fib(2) is  1
fib of 3 is  2  count of fib(2) is  1
fib of 4 is  3  count of fib(2) is  2
fib of 5 is  5  count of fib(2) is  3
fib of 6 is  8  count of fib(2) is  5
fib of 7 is  13 count of fib(2) is  8
None

由于问题对
n==2
情况的处理方式不同,因此可以在递归中使用另一个基本情况

def fib(n):
    """Assumes n is int > 0
    Returns Fibonacci Number of n and number fo times it was called"""
    if n == 0 or n == 1:
        return n, 0
    elif n == 2:
        return (fib(0) + fib(1)), 1
    else:
        f1, count1 = fib(n-1)
        f2, count2 = fib(n-2)
        return f1 + f2, count1 + count2

您可以通过向计算实际斐波那契数的函数添加一个可变参数来实现这一点,每次调用该函数时,该函数都会增加斐波那契数,并隐藏这样一个事实,即现在有一个额外的参数和一个提供该参数的包装函数:

我的意思是:

def dofib(n, count):
    """Assumes n is int >= 0
    Returns Fibonacci Number of n."""
    count[0] += 1
    if n==0 or n==1:
        return n
    else:
        return dofib(n-1, count) + dofib(n-2, count)

def fib(n):
    """Assumes n is int >= 0
    Returns Fibonacci Number of n and number of recursive calls."""
    count = [0]
    return dofib(n, count), count[0]

def testfib(n):
    for i in range(n+1):
        print('fib of {0} is {1[0]} (call count: {1[1]})'.format(i, fib(i)))

x=int(input('Enter a number: '))
print('Fibonacci of {0} is {1[0]} (call count: {1[1]})'.format(x, fib(x)))
testfib(x)
样本输出:

Fibonacci的7是13(呼叫计数:41)
0的fib为0(呼叫计数:1)
1的fib为1(呼叫计数:1)
2的fib为1(呼叫计数:3)
fib为3等于2(呼叫计数:5)
4的fib是3(呼叫计数:9)
5的fib是5(呼叫计数:15)
6的fib是8(呼叫计数:25)
7的fib是13(呼叫计数:41)

您可以通过向计算实际斐波那契数的函数添加一个可变参数来实现这一点,该函数每次调用时都会递增,并隐藏一个事实,即现在有一个额外的参数和一个提供该参数的包装函数:

我的意思是:

def dofib(n, count):
    """Assumes n is int >= 0
    Returns Fibonacci Number of n."""
    count[0] += 1
    if n==0 or n==1:
        return n
    else:
        return dofib(n-1, count) + dofib(n-2, count)

def fib(n):
    """Assumes n is int >= 0
    Returns Fibonacci Number of n and number of recursive calls."""
    count = [0]
    return dofib(n, count), count[0]

def testfib(n):
    for i in range(n+1):
        print('fib of {0} is {1[0]} (call count: {1[1]})'.format(i, fib(i)))

x=int(input('Enter a number: '))
print('Fibonacci of {0} is {1[0]} (call count: {1[1]})'.format(x, fib(x)))
testfib(x)
样本输出:

Fibonacci的7是13(呼叫计数:41)
0的fib为0(呼叫计数:1)
1的fib为1(呼叫计数:1)
2的fib为1(呼叫计数:3)
fib为3等于2(呼叫计数:5)
4的fib是3(呼叫计数:9)
5的fib是5(呼叫计数:15)
6的fib是8(呼叫计数:25)
7的fib是13(呼叫计数:41)

当全局计数器正常时,增加一个全局变量。但是为了保持练习的精神,在递归函数中使用累加器变量。当
n==2
全局计数器可以使用时,增加一个全局变量。但是为了保持练习的精神,在递归函数中使用累加器变量?这完全是矫枉过正。可以在递归函数中引入计数器作为累加器。和覆盖调用?为什么?@juanpa.ar