[Tutor] Recursion help
Justin Heath
justin@unixremedies.com
Fri Aug 1 09:44:02 2003
Gregor Lingl wrote:
> Justin Heath schrieb:
>
>> I am working thru some of the examples in the "Learning to Program"
>> tutorial. I am going thru the recusrion section and have gotten stumped.
>
>
> Hi Justin,
> one of the keypoints to understand recursion is understanding function
> calls. Let's consider a very simple NONrecursive example:
>
> >>> def printitem(item):
> print item
>
> >>> def myfun():
> printitem("Hello world!")
> printitem("Wow!")
>
> >>> myfun()
> Hello world!
> Wow!
> >>>
>
> Here we have defined two functions. The second one, myfun calls
> the first one, printitem, twice, with different arguments.
>
> You can make this visible, by inserting print statements, which give
> you information
> about entering and exiting the execution af a function:
>
> >>> def printitem(item):
> print "printitem(", item, ") entered."
> print item
> print "prititem(", item, ") exited."
>
> >>> printitem("Hi!")
> printitem( Hi! ) entered.
> Hi!
> prititem( Hi! ) exited.
> >>> def myfun():
> print "Myfun entered."
> printitem("Hello world!")
> printitem("Wow!")
> print "Myfun exited."
>
> >>> myfun()
> Myfun entered.
> printitem( Hello world! ) entered.
> Hello world!
> prititem( Hello world! ) exited.
> printitem( Wow! ) entered.
> Wow!
> prititem( Wow! ) exited.
> Myfun exited.
> >>>
>
> Observe, that here you have the original output, but additionally
> some "meta"-output, giving information about what's gong on
>
> Now, what concerns recursion, the difference is mainly that
> we have a function calling not another one but itself, with new
> arguments.
>
> But you can make visible what's going on in the same way, by inserting
> those print-statements for tracing execution: (Please continue reading
> below
> your code-snippet)
>
>> Here is the code I have run below:
>>
>> def printList(L):
>> # if its empty do nothing
>> if not L: return
>> # if its a list call printList on 1st element
>> if type(L[0]) == type([]):
>> printList(L[0])
>> else: #no list so just print print L[0] # now process
>> the rest of L printList(L[1:])
>>
>> myList=[1,2,3,4,5]
>>
>> printList(myList)
>>
>> The output is as follows:
>> 1
>> 2
>> 3
>> 4
>> 5
>
>
> Now we change your function, observing that there are two points
> where the functino may be exited:
>
> >>> def printList(L):
> print "printList(", L, ") entered."
> # if its empty do nothing
> if not L:
> print "printList(", L, ") exited."
> return
> # if its a list call printList on 1st element
> if type(L[0]) == type([]):
> printList(L[0])
> else: #no list so just print
> print L[0]
> # now process the rest of L
> printList(L[1:])
> print "printList(", L, ") exited."
>
> >>> printList([1,2,3,4,5])
> printList( [1, 2, 3, 4, 5] ) entered.
> 1
> printList( [2, 3, 4, 5] ) entered.
> 2
> printList( [3, 4, 5] ) entered.
> 3
> printList( [4, 5] ) entered.
> 4
> printList( [5] ) entered.
> 5
> printList( [] ) entered.
> printList( [] ) exited.
> printList( [5] ) exited.
> printList( [4, 5] ) exited.
> printList( [3, 4, 5] ) exited.
> printList( [2, 3, 4, 5] ) exited.
> printList( [1, 2, 3, 4, 5] ) exited.
>
> We can amend this, by using a variable calldepth, which
> we increment with every new call of printList and which we
> use to indent our meta-information by preceding our
> output string with " "*calldepth:
>
> >>> def printList(L, calldepth):
> print " "*calldepth + "printList(", L, ") entered."
> # if its empty do nothing
> if not L:
> print " "*calldepth + "printList(", L, ") exited."
> return
> # if its a list call printList on 1st element
> if type(L[0]) == type([]):
> printList(L[0], calldepth+1)
> else: #no list so just print
> print L[0]
> # now process the rest of L
> printList(L[1:], calldepth+1)
> print " "*calldepth + "printList(", L, ") exited."
>
> >>> printList([1,2,3,4,5], 1)
> printList( [1, 2, 3, 4, 5] ) entered.
> 1
> printList( [2, 3, 4, 5] ) entered.
> 2
> printList( [3, 4, 5] ) entered.
> 3
> printList( [4, 5] ) entered.
> 4
> printList( [5] ) entered.
> 5
> printList( [] ) entered.
> printList( [] ) exited.
> printList( [5] ) exited.
> printList( [4, 5] ) exited.
> printList( [3, 4, 5] ) exited.
> printList( [2, 3, 4, 5] ) exited.
> printList( [1, 2, 3, 4, 5] ) exited.
> >>>
>
> So you see, that each active instance of printList retains it's own
> value of L, as L is a local variable to the function printList
>
> Now you may wonder and try to understand how this comes:
>
> >>> printList([1,[2,3,4],5], 1)
> printList( [1, [2, 3, 4], 5] ) entered.
> 1
> printList( [[2, 3, 4], 5] ) entered.
> printList( [2, 3, 4] ) entered.
> 2
> printList( [3, 4] ) entered.
> 3
> printList( [4] ) entered.
> 4
> printList( [] ) entered.
> printList( [] ) exited.
> printList( [4] ) exited.
> printList( [3, 4] ) exited.
> printList( [2, 3, 4] ) exited.
> printList( [5] ) entered.
> 5
> printList( [] ) entered.
> printList( [] ) exited.
> printList( [5] ) exited.
> printList( [[2, 3, 4], 5] ) exited.
> printList( [1, [2, 3, 4], 5] ) exited.
> >>>
>
> Enough stuff to digest for now, I think. To that end play with it.
> Regards,
> Gregor
>
>
>
>
> _______________________________________________
> Tutor maillist - Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor
Gregor,
I see your point. If I had chosen to print the list every time I would
have seen the assignment when the funtioned 're-called" itself. I had
actually added some "debugging" print statements but only within the
if/else loops. I guess it goes to show that verbosity is a good thing.
Alos, thanks to you and everyone else for thier help. And unless I get
my head around my next topic I may be chiming in again later. :-)
Thanks,
Justin