#41. Рекурсивные функции | Python для начинающих

Поделиться
HTML-код
  • Опубликовано: 30 ноя 2024
  • Обучающий курс: stepik.org/cou...
    Что такое рекурсивные функции в Python. Как они работают. Примеры их использования.
    Telegram-канал: t.me/python_se...

Комментарии • 93

  • @андрейхоменко-и5я
    @андрейхоменко-и5я 3 года назад +118

    Открытый перелом мозга с необратимыми процессами.

    • @garalexalex9007
      @garalexalex9007 28 дней назад

      Да вроде не такая прям сложная тема, в отличие от циклов тех же.

  • @youcandoit1559
    @youcandoit1559 8 месяцев назад +18

    Урок классный, за пол года смотрю уже восьмой раз) Возможно когда-нибудь пойму. Спасибо

    • @xrilicc1154
      @xrilicc1154 6 месяцев назад

      Как успехи? Пробовали конспектировать материал?

    • @youcandoit1559
      @youcandoit1559 6 месяцев назад +1

      @@xrilicc1154 Вроде бы, с рекурсией прогресс есть🤘Понял про стек вызовов при рекурсии, разобрался в базовом и рекурсивном случае. Порешал еще немного задач🤏 Поэтому успехи есть💥

    • @xrilicc1154
      @xrilicc1154 6 месяцев назад

      @@youcandoit1559 отлично, я рад за вас! :)

  • @DmitryTimofeev
    @DmitryTimofeev 2 месяца назад +2

    Ура! Неделю разбирал последний пример и сегодня наконец досконально понял, как он работает. Спасибо за урок!

  • @coffeeglek6773
    @coffeeglek6773 Год назад +20

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

    • @utka111
      @utka111 Год назад +1

      Согласен. Чтобы лучше понять, надо посмотреть несколько раз через день-два, например. И обязательно своими руками писать код. Это важно. Писать надо по памяти из видео, а потом добавлять свои фишки и "играться". Очень полезно при этом пользоваться отладчиком и пошагово следить, что происходит в программе

  • @86Blind
    @86Blind 3 года назад +14

    Как же классно объяснена такая сложная тема. Здорово!

  • @paleface_brother
    @paleface_brother 3 года назад +25

    Большое спасибо! Ещё ни разу не встречал такое наглядное и доступное объяснение 👍🤝

  • @logdan
    @logdan Год назад +3

    добра и здоровья тебе! никакие скил боксы не тянут по качеству подачи!! СПАСИБО!

  • @sofiipochta
    @sofiipochta Год назад +2

    Спасибо, посмотрела!

  • @archibaldivanovich4103
    @archibaldivanovich4103 Год назад +5

    как chat объяснил
    Функция get_files рекурсивно обходит иерархию каталогов и файлов, описанную в словаре F, и выводит названия файлов и каталогов на экран.
    Аргумент path содержит текущий уровень иерархии (словарь с названиями файлов и каталогов и их содержимым), а depth - текущую глубину рекурсии (сколько раз функция вызывала сама себя). На каждом шаге рекурсии функция выводит название текущего файла или каталога, а затем проверяет, является ли содержимое текущего элемента словарем. Если это словарь, то функция вызывает сама себя рекурсивно, передавая в качестве аргумента содержимое элемента и увеличивая глубину рекурсии на 1. Если содержимое элемента - список, то функция просто выводит список с отступом.

  • @ZZZ5204
    @ZZZ5204 2 года назад +3

    Одно из лучших объяснений рекурсивных функций

  • @ПавелАнаньев-я2к
    @ПавелАнаньев-я2к Год назад +2

    Сергей, благодарю! Как всегда всё очень понятно и просто! Особенно за пример с файловой системой - очень круто красиво наглядно👍

  • @diplomdeady
    @diplomdeady 3 года назад +4

    Сергей, спасибо за ваши труды!

  • @user-tv9xp7uf6z
    @user-tv9xp7uf6z 5 месяцев назад +1

    Этот парень гений, лучше него никто не может объяснить

  • @_mrmark
    @_mrmark 2 года назад +5

    Пересматриваю регулярно. Почему нельзя каждый раз лайк поставить? )

    • @DmitriyKarpov-b1i
      @DmitriyKarpov-b1i Год назад +4

      То есть выполняете рекурсию. )

  • @Чуваш-ы3ц
    @Чуваш-ы3ц 3 года назад +15

    недавно я понял, что рекурсия мне начала нравится, я просто понял как она работает, благодаря лекциям автора в том числе) ну и после перечитывания "Грокаем алгоритмы". Ранее эту тему не допонял. Спасибо)

  • @andredru4278
    @andredru4278 9 месяцев назад +1

    Спасибо. Хорошие примеры.

  • @olegkomlev
    @olegkomlev 2 года назад +17

    Терминология. Если рекурсивная функция вызывает саму себя, то это ПРЯМАЯ РЕКУРСИЯ. А если она вызывает какую-то функцию, а та функция вызывает первоначальную - это КОСВЕННАЯ РЕКУРСИЯ. Может быть и более глубокая косвенность - одна функция вызывает другую, другая - третью, и т.д., а какая-то в этой цепочке вызывает первоначальную.
    Если функция делает не более одного рекурсивного вызова (т.е. либо возвращает результат, либо вызывает себя 1 раз), то это ЛИНЕЙНАЯ РЕКУРСИЯ. Если нарисовать вызовы такой рекурсии, то видим, что они выстроены в одну линию, а потом по этой же линии будет происходить возврат (в начале урока это наглядно показано).
    Функции recursive и факториал fact, показанные в уроке - примеры линейной рекурсии.
    Частный случай линейной рекурсии - ПОВТОРИТЕЛЬНАЯ РЕКУРСИЯ (называется также концевая или хвостовая рекурсия - tail recursion). Это если функция либо возвращает результат без рекурсивного вызова, либо делает рекурсивный вызов и сразу возвращает результат этого вызова, никак его не меняя и ничего больше не делая (рекурсивный вызов - последняя операция перед возвратом). Такая рекурсия легко может быть заменена циклом. Многие компиляторы опознают повторительную рекурсию и заменяют рекурсию на итерацию. Но, насколько знаю, Питон этого не делает (по крайней мере, несколько лет назад Гвидо Россум выстапал против такой оптимизации).
    В функции recursive рекурсия неповторительная (фунция выполняет print после рекурсивного вызова),. А функция fact модифицирует результат рекурсивного вызова перед возвратом (умножает результат на n), поэтому эта рекурсия тоже не повторительная.

    • @gairatakbarov9422
      @gairatakbarov9422 9 месяцев назад

      Этот комментарий надо закрепить я считаю

  • @aleksandr_nokhrin
    @aleksandr_nokhrin Год назад +1

    отличный практический пример !

  • @lun4ik739
    @lun4ik739 9 месяцев назад +2

    СПАСИБО!

  • @slizverg23
    @slizverg23 Год назад +5

    Сергей, в целом ваш контент пожалуй действительно лучший в рунете(да и не только), но ваш нейминг переменных… for f in path - тема и так непростая, а тут ещё и гадаешь мысленно, что за f такой:)
    Наверное, с опытом на такие вещи просто не обращаешь внимания, но новичкам было бы проще понять например: for folder in path - гораздо читабельнее же, хотя и длиннее на пару байт:)
    В целом же огромное спасибо за ваш труд)

  • @vladimirkulakov6126
    @vladimirkulakov6126 3 года назад +10

    Упражнения по рекурсивным функциям давались непросто)

  • @romanbush5164
    @romanbush5164 3 года назад +18

    Про рекурсии знал, а про обратный ход нет, 🙂

  • @ivanlino3747
    @ivanlino3747 3 года назад +6

    Спасибо большое, очень наглядно и как всегда интересно! Если есть возможность, было бы здорово посмотреть про хэш - функцию 🙂

    • @eugenedukatta9355
      @eugenedukatta9355 Год назад

      А что про хэш-функцию? Хэш-функция это функция в смысле математики, а не программирования. Это в общем смысле свертка данных любого размера к ограниченному размеру, по особому правилу (алгоритму). Таких функций можно придумать стотыщьпицот! Например, берете любое число любого размера и складываете его цифры. Если в сумме получилось число больше 99 - повторяем, и так далее. Как только получится число меньше 100 - останавливаемся, полученное число и будет результатом, называемым "хэш" от исходных данных.
      Пример: число 895475289549999278, складываем цифры получается 119 складываем еще раз получается 11. Это и есть хэш от числа 895475289549999278
      Это примитивный пример. Настоящие используемые на практике алгоритмы более сложные.

  • @Dmitrii-Zhinzhilov
    @Dmitrii-Zhinzhilov Год назад +1

    Благодарю! 👍🔥

  • @oopsimath
    @oopsimath 3 месяца назад +1

    else в вашей функции вычисления факториала избыточно, а условие должно проверять n == 1

  • @ВладиславАндреев-э8т
    @ВладиславАндреев-э8т 2 года назад +4

    На десятой минуте мозги закипели! Придется пересматривать, потому что на элементе path[f] мозги ломаются, хотя принцип вроде понятен до этого момента
    За труды большое спасибо

  • @newvanya
    @newvanya 8 месяцев назад +2

    Интересно, почему в примере факториала , значение n не пошло в отрицательную сторону, ведь условие все равно выполнится

  • @jamjam3337
    @jamjam3337 Год назад +1

    спасибо!

  • @return_1101
    @return_1101 2 года назад +5

    Боюсь представить что ждёт меня на практические задания.

  • @sergeyshestakov607
    @sergeyshestakov607 2 года назад +1

    спасибо помогло!

  • @sergeyv1534
    @sergeyv1534 3 года назад +1

    Класс!

  • @oleksiy.tryfonov8
    @oleksiy.tryfonov8 Год назад +1

    Подскажите, пожалуйста, если нет ветвлений, почему именно if используется, а не while?

  • @Psoglawec
    @Psoglawec 3 года назад +4

    Сам смысл рекурсии понял там где с числами (обратный процесс закрытия). А вот со словарём никак понять не могу, как происходит погружение в глубину?

  • @iiepe1915
    @iiepe1915 2 года назад +2

    Спасибо за видео, все понятно.
    Одну строчку только не понял, во втором примере, где написано (17) print, зачем нужен параметр f?

    • @selfedu_rus
      @selfedu_rus  2 года назад

      f - это обозначение F-строки в Python

    • @iiepe1915
      @iiepe1915 2 года назад

      @@selfedu_rus хм, понятно, просто её обычно видел в начале ставят, а тут переменная f цикла и f-строка, немного путает

  • @ИванИванов-й8н9д
    @ИванИванов-й8н9д 2 года назад +1

    круто

  • @АртемНиконов-у7я
    @АртемНиконов-у7я Год назад +1

    спасибо за урок!
    один вопрос :зачем перед depth нужна *

    • @VeihShizoo
      @VeihShizoo 17 дней назад

      Чтобы глубже входить можно было🥵

  • @nouchance
    @nouchance 3 года назад +1

    SERGEY✊

  • @SAPERPEducation
    @SAPERPEducation 3 года назад +3

    Правильно я понимаю, что если бы я вручную вычислял факторил например от 4-х то записал бы следующим образом 1*2*3*4, а функция с рекурсией делает это с конца 4*3*2*1

    • @selfedu_rus
      @selfedu_rus  3 года назад

      детали реализации уже не помню, но вроде так (факториал верно записан)

    • @symbiozzzzzzzzz
      @symbiozzzzzzzzz Год назад

      Почему, если выполнение происходит с последнего стэка? А в последнем стэке как раз единица

  • @eugenedukatta9355
    @eugenedukatta9355 Год назад +1

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

    • @selfedu_rus
      @selfedu_rus  Год назад

      в реальной жизни этими терминами программисты не пользуются (никогда не слышал), говорят просто: параметры со значениями по умолчанию или аргументы со значениями

    • @eugenedukatta9355
      @eugenedukatta9355 Год назад

      @@selfedu_rus Да, но по общепринятым правилам, включая другие языки программирования,
      Формальными параметрами называются переменные (имена), объявленные в заголовке функции и используемые внутри этой функции. Фактический параметр (или по-другому аргумент) это значение, передаваемое в функцию при ее вызове.
      У вас совершенно иной смысл. Фактическим параметром вы называете позиционные, формальным параметром вы называете параметр со значением по-умолчанию, к которому вы обращаетесь при вызове функции именованным аргументом.
      Кстати, я не единственный, кто высказывает свое недоумение в комментариях ваших видео, по данному вопросу.

  • @vitalybessonov6138
    @vitalybessonov6138 Год назад +1

    Штука прикольная, но в целом не эффективная. Видимо только для обхода дерева и подходит. Для факториалов и других прогрессий цикл проще и скорее всего быстрее. Автор обьяснил хорошо, рассказал про стек, про то, что при вызове следующей функции текущая как бы замораживается сохраняя текущие параметры. И так для каждого последующего вызова. И потом когда выполнится последняя, начинается путь обратно по стеку вызовов функций к изначальной постепенно размораживая функции и их параметры. Но все же, где рекурсия еще максимально полезна кроме обхода дерева?

    • @selfedu_rus
      @selfedu_rus  Год назад +1

      Вы правы, по скорости она проигрывает циклам (если задачу можно на циклы заменить). Но иногда скорость не имеет большого значения и глубина рекурсии небольшая. В этом случае для удобства реализации ее вполне можно применить.

  • @ЗНАКОМЫЙСВАРЩИК
    @ЗНАКОМЫЙСВАРЩИК 9 месяцев назад +1

    Подскажите, не совсем понятно в случае с факториалом за счет чего останавливается рекурсия.

    • @crok4u
      @crok4u 8 месяцев назад

      За счет if´a.

  • @СергейСмирнов-ь8у
    @СергейСмирнов-ь8у 3 года назад +1

    Лайк!

  • @musicforyou1380
    @musicforyou1380 11 месяцев назад +1

    это похлеще всяких кроссвордов "теребит мозговые нейроны")))

  • @ibrahimoglu
    @ibrahimoglu 3 года назад +1

    👍

  • @Иваниванов-д7у9о
    @Иваниванов-д7у9о Год назад +1

    В конце было все непонятно тк как использовалось многое чего не было дано ранее

  • @ДмитрийКрашенинников-г7ш

    Сергей. У меня рекурсивная функция по аналогии с Вашей закончилась на 984 итерации без ошибки в PYCharm. Не как у Вас. Это нормально? Кстати, рекурсивная функция мне напомнила эффект бумеранга. Если для понимания, как она работает.

    • @VeihShizoo
      @VeihShizoo 17 дней назад

      Другая версия Пайтона. Естественно не нормально, сноси Винду и все данные в нулину

  • @Tony-gx8ye
    @Tony-gx8ye 3 года назад +4

    я так и не понял, почему у нас функция начинает назад идти, у нас ведь значение value не меняется.

    • @ИНТЕР.КОМ
      @ИНТЕР.КОМ 3 года назад +4

      Она не идёт назад, она поочередно, с конца, закрывает полностью отработанные функции, выполняя необработанные фрагменты, которые как раз являются 4 3 2 1

  • @olegkomlev
    @olegkomlev 2 года назад

    Обобщенный пример повторительной рекурсии
    def F(X):
    if P(X):
    return H(X) # нерекурсивное вычисление
    else:
    return F(D(X)) # возврат рекурсивного вызова от модифицированного аргумента
    Может быть преобразовано в итеративную функцию
    def F(X):
    while not P(X):
    X=D(X)
    return H(X)
    Для примера рекурсивный способ вычисления алгоритма Евклида:
    НОД(a,b) = a, при a=b
    НОД(a,b) = НОД(a-b, b) при a > b
    НОД(a,b) = НОД(a, b-a), при b > a
    За Х (аргумент) принимаем пару (а,b). Условие прекращения рекурсии P(a,b) = a=b . А противоположное (условие продолжения рекурсии) not P (a,b) будет a != b. Модификатор аргумента D(X) будет такой
    D(a,b) = (a-b, b) при a > b
    D(a,b) = (a, b-a), при b > a
    На питоне модификатор D будет реализован так:
    if a > b:
    a=a-b # b = b
    else:
    b=b-a # a = a
    За нерекурсивное вычисление Н(Х) принимаем:
    H(a,b) = a
    Получаем рекурсивную функцию
    def get_nod(a, b):
    if a != b:
    return a # нерекурсивное вычисление
    else:
    # здесь придется записать в виде условного оператора с двумя ветвями, но рекурсивный вызов в каждый момент один
    if a > b:
    return get_nod(a-b, b)
    else:
    return get_nod(a, b-a)
    А если переделать в итеративную функцию по приведенному выше шаблону, получим программу из урока "#37. Алгоритм Евклида для нахождения НОД"

  • @ney107-iz6xl
    @ney107-iz6xl Год назад +1

    Если кто может распишите последний код
    Вроде понял но путаюсь
    Спасибо)

  • @mrdenzl3929
    @mrdenzl3929 2 года назад

    Вкратце, где применяются рекурсивные функции и какую задачу выполняют , для наглядности?
    Какую работу выполняют программисты с этой функцией?

    • @selfedu_rus
      @selfedu_rus  2 года назад +1

      Иерархический перебор чего-либо

  • @vadimgof8260
    @vadimgof8260 2 года назад +2

    А, если файлов, в каком-нибудь каталоге, будет больше 1000?

    • @selfedu_rus
      @selfedu_rus  2 года назад +2

      Либо увеличивать глубину рекурсии (есть настройки), либо не рекурсивный алгоритм применять.

    • @vadimgof8260
      @vadimgof8260 2 года назад +2

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

    • @selfedu_rus
      @selfedu_rus  2 года назад +1

      @@vadimgof8260 нет, правы )

    • @vadimgof8260
      @vadimgof8260 2 года назад +1

      @@selfedu_rus то есть не будет ошибкой, если я буду пользоваться циклом вместо такого рода функции, или же, всё-таки, есть какое-то правило/стандарт, который говорит, что в таких-то моментах надо использовать эту функцию?

    • @selfedu_rus
      @selfedu_rus  2 года назад +2

      @@vadimgof8260 да ладно вам, правил на все случаи жизни не напасешься ) просто здравый смысл в большинстве случаев и опыт

  • @olegkomlev
    @olegkomlev 2 года назад

    Обобщенный пример повторительной рекурсии с отложенными действиями, зависящими только от результата
    def F(X):
    if P(X):
    return H(X) # нерекурсивное вычисление
    else:
    return G(F(D(X))) # возврат рекурсивного вызова от модифицированного аргумента
    От чисто повторительной отличается дополнительным модификатором результата рекурсивного вызова G, т.е. после получения результата рекурсивного вызова функция что-то дополнительно делает с этим результатом, а только потом его возвращает. Ее преобразовать в итерацию сложнее.

  • @ney107-iz6xl
    @ney107-iz6xl Год назад +1

    Что значит depth?????

    • @selfedu_rus
      @selfedu_rus  Год назад

      глубина рекурсии

    • @ney107-iz6xl
      @ney107-iz6xl Год назад

      Спасибо за ответ
      это я понял что она тут делает
      На что влияет

  • @tizyanoonie8483
    @tizyanoonie8483 3 года назад +4

    Спасибо за урок!
    Пожалуйста, каталОг! Ведь Вы преподаватель, потом неправильно говорят Ваши студенты (

    • @selfedu_rus
      @selfedu_rus  3 года назад +6

      Спасибо! Почти нет ни одного человека, который бы все слова произносил верно, включая и вас :)

  • @nikolay7013
    @nikolay7013 Год назад

    Чтобы сделать матрешку, надо сделать матрешку...

  • @lorensio
    @lorensio Год назад +1

    Какой же у вас сексуальный голос... Умммм

  • @АнатолийКузнецов-ж6б
    @АнатолийКузнецов-ж6б 2 года назад +2

    Честно говоря ничего не понял. Зачем нужны рекурсивные функции, в каких кейсах нужно использовать именно их. Где без этих функций невозможно выполнить программу. Или где эти функции существенно упрощают код...

    • @selfedu_rus
      @selfedu_rus  2 года назад

      классика: перебор листьев бинарного дерева

    • @АнатолийКузнецов-ж6б
      @АнатолийКузнецов-ж6б 2 года назад +1

      @@selfedu_rus Почитал, посмотрел ещё. Перебор папок (то что Вы показали в ролике). В целом, получше стало, когда ещё допом инфу закинул. Вам спасибо за видео!

  • @АлександрВладимирович-ь3е

    Все ок только когда смотришь. Когда берешься кодить, вся логичность испаряется.
    Ну и "вэлуе" :) режет слух.

  • @vladvlad9555
    @vladvlad9555 Год назад +1

    ужас

  • @inkognito21blr1080p
    @inkognito21blr1080p 2 года назад +3

    автор объясняет рекурсию и при этом НЕ ОБЪЯСНЯЕТ почему она работает так, как работает.
    Функция напечатала 4 и завершила свою работу и мы перешли к предыдущей функции.
    А почему мы перешли к предыдущей функции? Я это просто должен принять как данность?
    Ладно, на этом этапе принял решение бросить курс и учить по другим источникам, ужасное объяснение тем

  • @valeriyn.144
    @valeriyn.144 5 месяцев назад +1

    КатАлог режет слух, можно ведь преподавателю правильное произношение слова выучить