干净简洁地编写一个递归函数

2024-09-27 00:17:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在写一个递归函数,它看起来像这样:

def mah_recursive_function(some_arg, some_option=True):
    if some_thing:
        some_arg.doFancyStuff();
        mah_recursive_function(some_arg,
                               some_option=some_option
        )
    elif some_thing:
        some_arg.doOtherFancyStuff();
        mah_recursive_function(some_arg,
                               some_option=some_option
        )

很明显,那些some_option=some_option赋值确实是多余的,而且,由于我有多个永久性的kwarg选项,这些多余的赋值变得非常烦人。你知道吗

from functools.magical_stuff import get_current_kwargs
mah_recursive_function(
    some_arg, **get_current_kwargs()
)

我不想用多余的行来填充我的递归调用。最好的办法是什么?你知道吗


Tags: truegetifdefargfunctionsomecurrent
2条回答

下面是一个我认为您希望通过递归实现的最小示例—通常每次都使用相同的值,但可以灵活地更改其中的一些值。这是你想要的吗?你知道吗

关键的一点是获取args/kwargs的副本,否则您将在任何时候更改某些内容时为每个未完成的调用修改args/kwargs。你知道吗

你可以用一个自动提供原件和复印件的装饰器来装饰它,也许甚至不必分出当前的名字。你知道吗

def factorial(*args_this_call, **kwargs_this_call):
    print('              -'
          '\nargs: {}'
          '\nkwargs: {}'.format(args_this_call, kwargs_this_call))
    # get copies so you don't modify the values of other calls that are waiting to complete
    args_next_call = list(args_this_call)
    kwargs_next_call = kwargs_this_call.copy()

    # you can break out the content of args / kwargs for clarity if you are going to use them a lot
    arg1, arg2 = args_this_call  # not used - just for example
    n = kwargs_this_call['n']

    # do your work
    if n == 1:
        return 1
    else:
        # modify whichever args/kwargs you want, leave the ones you don't want to change
        args_next_call[1] += 1  # some random modification
        kwargs_next_call['call_id'] += 1
        kwargs_next_call['n'] -= 1  # n-1 for factorial in this case

        # make the call
        result = n * factorial(*args_next_call, **kwargs_next_call)
        return result

# test the factorial with args/kwargs
args = (1, 1)  # just some values
kwargs = {'call_id': 1,
          'n': 4}
print(factorial(*args, **kwargs))

结果:

              -
args: (1, 1)
kwargs: {'call_id': 1, 'n': 4}
              -
args: (1, 2)
kwargs: {'call_id': 2, 'n': 3}
              -
args: (1, 3)
kwargs: {'call_id': 3, 'n': 2}
              -
args: (1, 4)
kwargs: {'call_id': 4, 'n': 1}
24

考虑使用包装函数以避免重复:

def recursive_func_wrapper(arg, option=True):
    def recursive_func(arg):
        if option: recursive_func(new_arg)
        else: recursive_func(new_arg2)
    return recursive_func(arg)

您的选项将自动传播(作为局部变量)到内部函数,该函数可以像往常一样递归,而不必重复option=参数。你知道吗

相关问题 更多 >

    热门问题