创建一个带有计数器的递归函数



我想创建一个具有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(可以工作,但我不允许使用全局变量

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

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

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

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))

最新更新