#python #recursion #fibonacci
#python #рекурсия #фибоначчи
Вопрос:
Я хочу написать рекурсивную функцию на Python для Фибоначчи.
x
будет начальной точкой, y
будет последующей x
и l
будет длиной.
Я не понимаю, в чем моя ошибка в мышлении:
def fib(x, y, l, fibList=None):
fibList = []
z = x y
x = y
fibList.append(z)
y = z
if len(fibList) <= l:
return fib(x, y, l, fibList)
else:
return(fibList)
Результат:
RecursionError: maximum recursion depth exceeded while calling a Python object
Я могу решить это с помощью цикла for, но не с помощью рекурсивной функции.
Комментарии:
1. Почему бы вам не распечатать значения
x
,y
,l
, иfibList
при вводе функции посмотреть, соответствуют ли они вашим ожиданиям.2. вы можете прочитать это programiz.com/python-programming/recursion на странице есть визуальное объяснение того, что происходит в функции рекурсии
3. Я имею в виду, что кто-то дал вам решение, но ошибка в том, что в начале каждого вызова функции fib вы очищаете свой список Фибоначчи.. таким образом, длина списков всегда будет <= 1, таким образом, вы столкнетесь с бесконечным циклом рекурсии, что нехорошо. добавьте что-то вроде «if fibList == None: …»
4. Пожалуйста, имейте в виду, что ваш код не даст вполне правильного результата даже с исправлением, предложенным другими ответами. Последовательность Фибоначчи начинается с
0
члена, а затем с двух1
членов. Невозможно вызвать вашу функцию так, чтобы она произвела первые два члена. Например, единственный способ получить ноль — это передать0
обаx
иy
, и это, конечно, не приведет к правильному получению каждого члена в последовательности. Смотрите мой ответ, который решает эту проблему, а также проблему бесконечной рекурсии, а также предоставляет модификацию вашей функции, чтобы сделать ее более удобной для вызывающего абонента.
Ответ №1:
Здесь есть несколько проблем. Как только вы исправите бесконечную рекурсию, у вас все еще будет проблема.
Как указывает @Raqha, вам не нужно инициализировать свой список при каждом вызове fib
функции, а только в первый раз, когда fibList
параметр не указан и поэтому по умолчанию None
используется значение .
Ваш код не может сгенерировать первые два числа в последовательности, 0
и 1
. Вы можете исправить это, просто инициализировав свой список, включив в него эти термины, и скорректировав логику, чтобы предоставить только N-2 дополнительных термина.
Сигнатура вашей функции может быть улучшена, чтобы вызывающей стороне было намного проще ее использовать. Вызывающий абонент заботится только о количестве терминов, которые он / она хочет. Пользователю не нужно знать, что вводить для начальных x
значений и y
значений.
Вот версия вашего кода с исправлением бесконечной рекурсии, исправлением недостающих терминов, а также с измененной подписью, чтобы пользователь мог вызывать функцию просто и очевидно:
def fib(l, x=0, y=1, fibList=None):
if fibList is None:
fibList = [0, 1]
z = x y
x = y
fibList.append(z)
y = z
if len(fibList) < l-1:
return fib(l, x, y, fibList)
else:
return(fibList)
print(fib(10))
Результат:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
Ответ №2:
Во второй строке, которую вы задаете fibList = []
. Это означает, что каждый раз, когда вы вызываете функцию рекурсивно, она сбрасывает список пустым, поэтому len(fibList)
всегда будет равно 1.
Удалите эту строку, чтобы переменная fibList не сбрасывалась, тогда она должна правильно соответствовать вашему условию выхода. Как это написано, теперь оно работает вечно, пока не сломается.
Ответ №3:
В начале каждого fib
вызова функции вы очищаете свой fibList
with fibList = []
. Таким образом, длина списка всегда будет <= 1
равна, поэтому вы сталкиваетесь с бесконечным циклом рекурсии, что не очень хорошо. Вам нужно добавить что-то вроде if fibList is None:
При первом вызове функции «fib» без предоставления какого-либо 4-го оператора в списке аргументов, значение fibList изначально будет равно «None». Но позже, когда вы снова рекурсивно вызываете функцию «fib», вы предоставляете список fibList в списке аргументов. Таким образом, значение больше не равно «None». Поэтому при добавлении оператора if, как упоминалось выше, функция знает, когда вы вызываете функцию извне (когда вы вызываете ее в своем коде как «fib (1,2,10)»), или когда функция рекурсивно вызывает саму себя. И поэтому вы не сбрасываете список файлов каждый раз, когда вызываете функцию, а устанавливаете его только 1 раз в начале.
def fib(x, y, l, fibList=None):
if fibList is None:
fibList = []
z = x y
...
Комментарии:
1. что он делает, «если fibList == None:»? если fibList равен None, он создает новый пустой список, в противном случае он добавляется к списку правильно?
2. Если список Фибоначчи еще не инициирован, он инициирует его -> fibList = [] . Затем вы добавляете новый fib в этот список, в следующем операторе if вы ищете его длину. То есть на первой итерации 1, когда ваша переменная l больше 1, вы снова вызовете эту функцию, но на этот раз с заданным списком fibList, поэтому ваш список fib больше не None, поэтому оператор if является ложным и не сбрасывает ваш список fibList . знайте, что длина списка может расти до тех пор, пока не достигнет переменной l, тогда 2-й оператор if равен false, таким образом, вы возвращаете fiblist
3. @Raqha, вы должны указать комментарий выше в своем ответе. это хороший материал