Как создать рекурсивную функцию, которая генерирует несколько циклов for и подсчитывает общее время

#python #for-loop #recursion #counting

#python #цикл for #рекурсия #подсчет

Вопрос:

Я попытался подсчитать общее количество вызовов с помощью рекурсивной функции, которая генерирует n циклов for, но переменная, похоже, никогда не меняет своего значения.

 a=0

def recursivelooping(times,volumes):
    if times==0:
        a =1
    else:
        for i in range(volumes):
            return recursivelooping(times-1,i)
  

Результат должен больше походить на приведенную ниже переменную a , но вместо этого я всегда получал ноль.

 def multiforloop(volumes):
    a=0
    for i in range(volumes):
        for j in range(i):
            for k in range(j):
                a =1
    print(a)
  

Комментарии:

1. Какое значение times изначально?

2. используйте global a в начале функции (плохая практика, но решает вашу проблему)

3. Помимо проблемы с глобальной переменной, ваша функция также возвращается слишком рано. (Поскольку base регистр фактически ничего не возвращает, рекурсивные регистры тоже этого не делают; просто отбросьте return ключевое слово.)

Ответ №1:

Если я правильно понимаю, закрытие, возможно, является самым коротким решением:

 def recursivelooping():
    a = 0
    def f(times, volumes):
        nonlocal a
        if volumes == 0:
            return a

        # Inner loop
        for t in range(times):
            for j in range(volumes):
                a =1

        # Outer loop
        return f(times, volumes-1)
    return f

def multiforloop(times, volumes):
    a=0
    for i in range(volumes 1):
        for t in range(times):
            for j in range(i):
                a =1
    return a

print(recursivelooping()(1, 10))
print(multiforloop(1, 10))
  

Это выведет 55 для обоих (как в n * (n 1) / 2). Замыкание — это просто функция (здесь f ), сопровождаемая средой (некоторый контекст, который отображает имена в переменные, здесь a только). Это означает, что она a доступна изнутри f , как если бы это была локальная переменная, но это не совсем локальная переменная, это свободная переменная

При написании a = 1 обычным поведением является поиск локальной переменной с именем a , вместо этого здесь a указана свободная переменная, вот почему нам нужно добавить nonlocal ключевое слово, чтобы указать это.

Комментарии:

1. @Idlehands Это совершенно разные вещи… с помощью nonlocal вы можете сбросить состояние простым вызовом recursive_closure . С global вы в основном облажались, вручную сбрасывая переменную по модулю. Также с помощью global вы просто не можете использовать многопоточность, когда у вас есть две из этих функций, запущенных одновременно, но с помощью nonlocal вы можете просто «создать» два отдельных счетчика. Я часто использую приведенную выше идиому для key функций, где мне нужно поддерживать некоторое состояние в groupby или подобном. Это просто не сработало бы при использовании global .

2. Если это recursivelooping (2, 10), разве значение не должно быть 45? поскольку итеративный способ выполнения этого дал результат.

3. Если вам не нравится этот подход, то вы можете «потратить» еще несколько строк, чтобы сделать это классом (с атрибутом class a ).

4. Рекурсивная версия выполняет итерации другим способом (3 цикла вместо 2)

5. Я опубликовал фрагмент кода с двумя функциями, которые ведут себя точно так же.