Рубрики
Без рубрики

В Python Как рекурсия работает во время выполнения

Фото Мартина Адамса) на Unsplash…

Автор оригинала: feroz khan.

Фото: Мартин Адамс on Unsplash

Рассмотрим приведенный ниже фрагмент кода, который имеет две функции foo и main. Специальная переменная __name__ , которая в основном задается интерпретатором python перед выполнением, и ее значение устанавливается в __main__ при выполнении в качестве основной программы.

В python, если функция не заканчивается оператором return или имеет оператор return без какого-либо выражения, возвращается специальное значение None.

#!/usr/bin/python

def foo(msg):
    print '{} foo'.format(msg)

def main():
    msg = 'hello'
    foo(msg)

if __name__ == '__main__':
    main()

# end

Чтобы определить выходные данные приведенного выше кода, нам нужно знать, в каком порядке Python выполняет строки кода. Мы можем запустить его и получить результат, но дело не в этом.

Интерпретатор Python выполняет код с отступом уровня 0. В приведенном выше случае метод main() будет выполняться как его отступ на уровне 0. Это начальная точка выполнения программы, и ход выполнения сохраняется в стеке времени выполнения.

Что такое стек времени выполнения?

Это простой стек времени выполнения, в котором кадры вызова добавляются в стек, и они выскакивают один за другим, пока он не достигнет последнего кадра в стеке, а затем выполнение завершается.

Это простой стек времени выполнения, в котором кадры вызова добавляются в стек, и они выскакивают один за другим, пока он не достигнет последнего кадра в стеке, а затем выполнение завершается.

Это стек времени выполнения для нашего простого примера программы.

Это стек времени выполнения для нашего простого примера программы.

Каждый блок в стеке называется кадром вызова, он же записи активации. Они хранятся в памяти, чтобы отслеживать выполнение вызова функции, и выделенная память освобождается при возврате функции.

Фрейм вызова добавляется поверх стека при вызове функции и удаляется при возврате функции. Он содержит имя функции, которая была вызвана, и место, откуда ее можно забрать(номер строки) при возврате функции.

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

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

Ниже приведена простая программа для добавления чисел из списка с помощью рекурсии.

#!/usr/bin/python

def sum_list(l):
    if not l:
        return 0
    return l[0] + sum_list(l[1:])

def main(l):
    total = sum_list(l)
    print total

if __name__ == '__main__':
    main([1, 2, 3])

# end

Ниже приведена трассировка стека вышеприведенной программы для рекурсивного получения суммы чисел в списке.

Ниже приведена трассировка стека вышеприведенной программы для рекурсивного получения суммы чисел в списке.

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