使用计数器创建递归函数

时间:2018-07-26 09:01:44

标签: python python-3.x recursion

我想用2个参数(步骤,数字)创建一个递归函数。

在递归内发生一些带有数字的操作,并使用步骤1和新的数字再次调用该函数。

steps == 0一开始我要增加一个计数器,所以我看到遇到了多少个调用步骤0的函数,具体取决于函数中的算法。

有没有办法做到-没有全局变量或其他参数,两者都不可能!

我尝试过:

if not counter in locals():
   counter=0

但这不能正常工作

UnboundLocalError: local variable 'counter' referenced before assignment

此处为完整代码:

def IsaacRule(steps, number):


if not counter in locals():
    counter = 0

    if steps == 0:
        counter+=1
        return counter

    if ((number - 1) / 3) % 2 == 1:
        IsaacRule(steps-1, (number - 1) / 3)

    if (number * 2) % 2 == 0:
        IsaacRule(steps-1, number*2)

    return counter

具有全局变量(并且函数外部的counter = 0)可以正常工作-但我不允许使用全局变量

2 个答案:

答案 0 :(得分:0)

一种可能的解决方案是使用自定义可调用类型:

class MyRecursiveFunc(object):
    def __init__(self):
        self.counter = 0
    def __call__(self, steps, numbers):
        if steps == 0:
            self.counter += 1
        results = self.do_something(steps, numbers)
        if some_condition():
            results.extend(self(steps-1, numbers))
        return results

func = MyRecursiveFunc()
results = func(steps, numbers)
print(func.counter)

另一种方法是将臭名昭著的“默认可变参数”陷阱变成您的优势:

def IsaacRule(steps, number, _counter=[0]):
    if steps == 0:
        _counter[0] += 1
    else: 
        if ((number - 1) / 3) % 2 == 1:
            IsaacRule(steps-1, (number - 1) / 3)

        if (number * 2) % 2 == 0:
            IsaacRule(steps-1, number*2)

    return _counter[0]

或者如果您唯一关心的结果是计数器,则可以在进行递归调用时更新它:

def IsaacRule(steps, number):
    if steps == 0:
        return 1

    counter = 0
    if ((number - 1) / 3) % 2 == 1:
        counter += IsaacRule(steps-1, (number - 1) / 3)

    if (number * 2) % 2 == 0:
        counter += IsaacRule(steps-1, number*2)

    return counter

答案 1 :(得分:0)

您可以在函数本身中存储计数器:

def IsaacRule(steps, number):
    if steps == 0:
        IsaacRule.counter+=1
        return IsaacRule.counter

    if ((number - 1) / 3) % 2 == 1:
        IsaacRule(steps-1, (number - 1) / 3)

    if (number * 2) % 2 == 0:
        IsaacRule(steps-1, number*2)

    return IsaacRule.counter

IsaacRule.counter = 0
print(IsaacRule(10, 1000))