#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. Я опубликовал фрагмент кода с двумя функциями, которые ведут себя точно так же.