我想练习递归和装饰器并尝试做这个简单的功能,但它不起作用:
def dec(func):
def wrapper(number):
print("Recursive count:")
rec_cou(number)
return wrapper
@dec
def rec_cou(number):
""" Count from 0 to a given number from 50 and up """
if number == 0:
print(number)
return number
num = rec_cou(number - 1)
print(num + 1)
return num + 1
rec_cou(53)
单独的递归函数效果很好,但是当我添加装饰器时会产生错误:超出最大递归深度
答案 0 :(得分:2)
装饰者有两个问题:
func
。None
另外,目前你的装饰师没有计算任何东西......试试这个:
def dec(func):
func.count = 0 # give each decorated function its own counter
def wrapper(number):
print("Recursive count: %d" % func.count)
func.count += 1 # increase counter
return func(number) # call original function 'func' and return result
return wrapper
更新:从你的评论中,我似乎误解了你的装饰师应该做什么,你误解了装饰者的工作方式。第一次调用函数时,装饰器不会被调用一次,但它用装饰器中定义的函数替换函数。换句话说,
@dec
def foo(...):
...
相当于
def foo(...):
...
foo = dec(foo)
即。当装饰函数时,装饰器只调用一次,每次调用原始函数时调用装饰器中构造的函数,替换它。如果你只想打印一次,要么使用另一个答案中的装饰器,要么根本不使用装饰器:只需创建一个打印然后调用该函数的包装器。这对于为递归函数提供“入口点”并不罕见。
def print_and_run(number):
print("Recursive count:")
rec_cou(number)
BTW,这是我通常用于可视化递归调用的装饰器:
def trace(f):
trace.depth = 0
def _f(*args, **kwargs):
print " " * trace.depth, ">", f.__name__, args, kwargs
trace.depth += 1
res = f(*args, **kwargs)
trace.depth -= 1
print " " * trace.depth, "<", res
return res
return _f
答案 1 :(得分:2)
要解决最大递归深度问题,请调用传递给装饰器(func
)而不是rec_cou
的函数,并返回函数调用的值。也就是说,在第5行,将rec_cou(number)
替换为return func(number)
。
编辑:
def decorate(function):
def wrapper(parameter):
if wrapper.initial:
print("Recursive count:")
wrapper.initial = False
result = function(parameter)
wrapper.initial = True
return result
wrapper.initial = True
return wrapper
@decorate
def count(number):
""" Prints integers on the interval [0, number] """
if number:
count(number - 1)
print(number)
count(53)
没有装饰者:
def count(number):
""" Prints integers on the interval [0, number] """
if number:
count(number - 1)
else:
print("Recursive count:")
print(number)
count(53)
答案 2 :(得分:0)
如果您想要的是函数rec_cou
在递归下降之前打印某些内容,只需修改该函数并且不要担心装饰器。
def rec_cou(number, internal_call=False):
""" Count from 0 to a given number from 50 and up """
if not internal_call:
print "Now performing recursive count, starting with %d" % number
if number == 0:
return number
num = rec_cou(number - 1, internal_call=True)
return num + 1
正如我在评论中提到的,我所做的就是接受乔尔答案背后的想法(这是为了添加变量 - 我称之为&#34;标志&#34; - - 指示函数是在外部调用还是作为递归的一部分调用)并在函数本身内移动了标志变量(我称之为internal_call
,而Joel称之为initial
)。
此外,我不确定所有这些num
业务是关于什么的。请注意:
0
案例,rec_cou
返回0。number > 0
,num
设置为rec_cou(number-1)
返回的值,然后返回1+num
。例如,在rec_cou(1)
的情况下,num
设置为rec_cou(0)
,即0
,则返回0 + 1
,即1
{1}}。同样,对于rec_cou(2)
,返回的值超过rec_cou(1)
的值,因此会返回2
。
简而言之,对于每个自然数,rec_cou(number)
都会返回输入数字的值。它不清楚你想要实现的目标,但你所获得的是身份功能,这似乎不太可能是你想要的。