Как работает рекурсивная функция, Python

Есть вот такая функция

    def get_line_list(d, a=[]):
        for i in d:
            if type(i) != list:
                a.append(i)
            else:
                get_line_list(i)
        return a
    
    
    print(get_line_list([1, 2, [True, False], ["Москва", "Уфа", [100, 101], ['True', [-2, -1]]], 7.89]))

Первый параметр - многомерный список, второй параметр - пустой список, в который нужно переместить все элементы из первого и при этом распаковать их, чтобы список в итоге вышел одномерным.

Вопрос: в какой вообще момент рекурсивная функция здесь распаковывает списки? Как это происходит?

Второй вопрос: насколько вообще нужно запариваться над темой рекурсии, часто ли она применяется на практике? Это какой-то мрак и хотелось бы знать, стоит ли вообще мучиться и понимать её?


Ответы (2 шт):

Автор решения: Сергей

"Распаковывается" список в момент, когда рекурсивная функция, начинает работать со списком. Сначала for i in d идет по начальному списку. Затем, как только if type(i) != listобнаруживает, что компонент [True, False] - список, то идет рекурсовный вызов и for i in d в вызванной функции "распаковывает" этот мини-список. И так далее.

Советую посмотреть самому в пошаговом отладчике, что происходит, а то голову сломаете. Вот ссылка на другой мой ответ, где про отладчик самое необходимое говорится (ну, или print используйте, про него там тоже есть): Ошибка в коде генерации пароля. Просьба помочь найти причину, дать пояснение

2. Рекурсия применяется не очень часто, но применяется. Понимать её надо, хотя бы для того, чтобы знать, как переделать алгоритм, чтобы от нёё избавиться. В Python любую программу можно переписать без рекурсии, но иногда это будет сложно. Лучше жить без неё (быстрее работает код, как правило, на стек меньше нагрузка), но в алгоритмах она встречается.

Вот ссылка на простые советы, как от неё избавляться в базовых случаях: Простые решения проблем с рекурсией

→ Ссылка
Автор решения: Vadim Tukaev

Кстати, мнѣ эта функція очень не нравится. Условіе съ двумя отрицаніями, неявная передача параметра, и вообще… Но если не переписывать всё съ нуля, а только причесать имѣющееся, то я бы такъ сдѣлалъ:

def get_line_list(d):
    a = []
    for i in d:
        if type(i) == list:
            a.extend(get_line_list(i))
        else:
            a.append(i)
    return a

Что касается того, зачѣмъ нужна рекурсія, то это странный вопросъ. Затѣмъ же, зачѣмъ и любой другой инструментъ, пусть даже абстрактный. Очень часто рекурсивное рѣшеніе получается самоочевиднымъ, изящнымъ и лапидарнымъ. Рекомендую порѣшать задачи на рекурсию. Вотъ мой любимый примѣръ: написать функцію, которая изъ трёхъ чиселъ выбираетъ среднее, т. е. такое, которое располагается на числовой оси между двумя остальными. Попробуйте придумать, гдѣ тамъ примѣнить рекурсію.

→ Ссылка