2013-09-19 2 views
1

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

так вот код, который только на основе от простого примера, который я нашел на YouTube,

def count(n): 
    if n > 0: 
     print "Count 1", ", ", n 

     count(n - 1) 

     print "Count 2", ", ", n 
    else: 
     print "Done" 

count(1) 

и это то, что он печатает,

граф 1, 1

Done

Кол-во 2, 1

Что я ожидал, было

граф 1, 1

Совершено

Совершено

Мое понимание (что, конечно, не так), что граф (1) (для внешнего счетчика функции) будет называться и потому что 1 больше 0, будет печатать 1, затем подсчет (1 - 1) (функция внутреннего счета) вызовет счетчик (0) (функция внешнего счета), а так как 0 не больше 1, это напечатает Done. Затем я подумал, что возврат из счета (1 - 1) (функция внутреннего счета) также будет возвращен Done, и поскольку не было других n значений, введенных во внутренний счет(), это было бы так. Я не понимаю, как сделали отпечатки один раз и 1 печатает дважды ???

+1

Рекурсивный вызов не изменяет значения локальных переменных в текущем вызове. Поэтому ваше понимание неверно (также потому, что функция ничего не возвращает, поэтому ваш разговор о «return Done» не имеет большого смысла). – vanza

+0

вы можете использовать встроенный отладчик и пройти через строку кода по строке 'import pdb; pdb.set_trace(); ' – dm03514

ответ

5

Поедем через функцию вручную для ввода 1:

  • count(1) называется (n является 1):
    • n > 0 является верно, поэтому (если пункт):
      • Печать Count 1 , 1n есть 1 здесь)
      • count(0) называется (n является 0):
        • n > 0 является ложным, так (иначе пункт):
          • печати Done
      • печати Count 2 , 1n является 1 здесь)

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

Вы также можете думать о упрощенной версии вашей функции, удаляя те первые два заявления для печати, так как они не должны влиять сколько раз "Done" напечатано:

def count(n): 
    if n > 0: 
     count(n - 1) 
    else: 
     print "Done" 

Теперь она должна быть гораздо яснее, что "Done" будет печататься только один раз:

  • count(1) под названием (n является 1):
    • n > 0 является верно, поэтому (если пункт):
      • count(0) называется (n является 0):
        • n > 0 является ложным, так (иначе пункт):
          • печати Done
+0

Хорошо, спасибо, это имеет смысл. На youtube был урок, и учитель говорил о «неявном возвращении», которое меня смутило и заставило задуматься о том, что счет (n - 1) что-то возвращает? – jc72

0

Когда вызов count(n-1) возвращается, он продолжает работать следующие строки, в этом случае, другая печать с графом 2.

0

Поскольку печать «Готово» в блоке еще происходит только в вызовах сосчитать, когда n < = 0. В первом вызове с n = 1 этот оператор не будет выполнен, он будет исполняться только во втором, рекурсивном вызове, когда n равно 0.

1

Давайте сделаем простое расширение функции count чтобы узнать, что действительно происходит:

def count0: 
    print "Done" 

def count1: 
    print "Count 1, 1" 
    count0() 
    print "Count 2, 1" 

Как вы можете видеть, count1 (и действительно любой count(n) для n> 0) никогда не будет печатать "Done". Так что это только когда-либо печатается один раз.

0

после того, как печатает первую строку Count 1, 1

он вызывает метод, который будет печатать Готово, потому что п теперь-так проваливает если условие.

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

которая печать граф 2, 1, потому что п не изменила свое значение (если п = п-1, n будет равно 0).

1

Ваш сценарий имеет два заявления

  1. Определение count
  2. Вызов count с аргументом 1.

count Так называется и n 1. Начиная с n больше, чем 0, вы выполняете эти три строки в порядке

print "Count 1", ", ", n # ===> which prints Count 1, 1 

    count(n - 1)    # ===> which prints Done 

    print "Count 2", ", ", n # ===> which prints Count 2, 1 

Как и во всех рекурсивных функций, не пытаются overthink вещи и проследить во внутренние вызовы. Посмотрите на скрипт только с верхнего уровня и пусть рекурсия сделает свою магию. Ваш вызов выполнил три строки. Конечно, внутренняя линия была рекурсивным вызовом, но не беспокойтесь об этом, пока не выясните, что делают другие линии.

И, кстати, каждый рекурсивный вызов получает свою собственную копию на n, поэтому «внешнее значение» не влияет. Конечно, вы можете написать рекурсивный код, который имеет побочные эффекты, но вы действительно не хотите этого делать.

0

Я думаю, что вы ошибаетесь, так как ничего не происходит с возвращаемым значением count (n-1).

Первый вызов для подсчета с n = 1 отпечатками «Count 1,1», тогда вызывается count (0). В этом вызове n = 0, поэтому он печатает «Готово» и возвращается. Теперь мы вернулись в счет (1), сразу после вызова для подсчета (0). Затем мы просто делаем следующее утверждение, которое печатает «Count 2, 1», потому что n здесь 1. Тогда мы закончили.

+0

Ahhhhhh да, это то, о чем я тоже интересовался, спасибо !!!! Я не мог понять, с какого числа() код закончился, что бы напечатать и почему? Это действительно помогло мне понять спасибо. – jc72

Смежные вопросы