带有 kwargs 的递归函数

Recursive function with kwargs

我想要一个递归接受 kwargs 的函数。我怎样才能传递 kwargs?

代码示例:

def recursion(a, b, **kwargs):
    if a == 1:
        print(a + b)
    elif a == 2: 
        print(a + b + kwargs['name']
    else:
        a = a/2
        recursion(what to put in here?)
def re(a, b, **kwargs):
    print(a + b, kwargs['name'])
    if a == 0:
        return
    else:
        re(a-b,b,**kwargs)

re(5,1,name='Hello World!')

这将为您提供以下输出

6 Hello World!
5 Hello World!
4 Hello World!
3 Hello World!
2 Hello World!
1 Hello World!

最近遇到了类似的问题,我想出了以下问题:

from functools import wraps
from inspect import currentframe

def recursive_kwargs(fun):
    ''' Persist keyword arguments through recursive calls '''
    @wraps(fun)
    def wrapper(*args,**kwargs):
        caller_name = currentframe().f_back.f_code.co_name
        if caller_name is fun.__name__:
            fun(*args,**fun.__kwargs__)
        else: # Top of the recursive stack
            fun.__kwargs__ = kwargs
            fun(*args,**kwargs)
    return wrapper

然后你就可以装饰你的函数了,它应该自己工作而不传递任何 kwargs:

@recursive_kwargs
def fib(n, codename='spam', password='eggs'):
    print(codename, password)
    if n == 1:
        return 1
    return fib(n-1) # Don't pass any kwargs

现在 fib(3) returns spam eggs(3 次),fib(3,codename='Vikings') 确实 return Vikings eggs(3 次)。

这很可爱也很方便,但是 ,这都是由于 @wrapscurrentframe 查找。这里有一些 timeit 结果:

fib:  [3.69, 3.24, 2.82, 2.57, 2.56] us # As defined above
fib2: [1.45, 1.14, 1.15, 1.08, 1.08] us # With just the @wraps (but doing nothing)
fib3: [0.58, 0.66, 0.68, 0.54, 0.48] us # Just passing the kwargs along manually

TLDR:除非您不关心效率,否则@Harish 的回答可能就是这样做的方法。例如,如果你正在处理一个浅层(恒定深度,甚至)递归堆栈,其中瓶颈是函数本身的主体,而不是递归(又名肯定 而不是 我已经举过的例子在这里使用)。

还有;不要在没有记忆的情况下使用递归来计算斐波那契数(参见 here 了解更多信息)