Lecture 27

Recursion

MCS 260 Fall 2020
David Dumas

Reminders

  • Work on Project 3 ASAP. Do not delay!
  • Quiz 9 due today at 6pm Central
  • OOP loose end: protocols

    We implemented the sequence protocol last time. There are others.

    Still more can be found in the collections.abc module, which contains classes you can subclass when implementing the protocols.

    Recursion

    A function in Python can call itself. This can be useful, for example if the result of the function at one argument is easy to obtain from the result at another argument.

    This technique is called recursion. A function which uses it is a recursive function.

    Factorial

    The classic example of recursion (being easiest to understand) is the computation of factorials:

    $ n! = n \times (n-1) \times (n-2) \times \cdots 2 \times 1$

    e.g. $5! = 5 \times 4 \times 3 \times 2 \times 1 = 120$

    Critical observation: $n! = n \times (n-1)!$

    Recursive factorial

    Let's build a function fact(n) that uses $n! = n \times (n-1)!$ as the basis of its operation.

    Call stack

    Python keeps track of all the function calls that are underway in a stack. Items on the stack indicate where the call originated.

    Calling a function pushes an item on the stack.

    Returning pops an item form the stack.

    There is a maximum allowed stack size. Exceeding it is a stack overflow.

    Computing fact(3)

    If push is list.append and pop is list.pop:

    call_stack == [
            ]
        

    Note "top" of stack is the last element.

    Computing fact(3)

    If push is list.append and pop is list.pop:

    call_stack == [
                Called fact on line 30 with argument 3
            ]
        

    Note "top" of stack is the last element.

    Computing fact(3)

    If push is list.append and pop is list.pop:

    call_stack == [
                Called fact on line 30 with argument 3,
                Called fact on line 18 with argument 2
            ]
        

    Note "top" of stack is the last element.

    Computing fact(3)

    If push is list.append and pop is list.pop:

    call_stack == [
                Called fact on line 30 with argument 3,
                Called fact on line 18 with argument 2,
                Called fact on line 18 with argument 1
            ]
        

    Note "top" of stack is the last element.

    Computing fact(3)

    If push is list.append and pop is list.pop:

    call_stack == [
                Called fact on line 30 with argument 3,
                Called fact on line 18 with argument 2
            ]
        

    Note "top" of stack is the last element.

    Computing fact(3)

    If push is list.append and pop is list.pop:

    call_stack == [
                Called fact on line 30 with argument 3
            ]
        

    Note "top" of stack is the last element.

    Computing fact(3)

    If push is list.append and pop is list.pop:

    call_stack == [
            ]
        

    Note "top" of stack is the last element.

    Recursive delete

    How can we make a function delete(fn) that will delete fn if it is a file, or which will remove all files and directories inside fn and then remove fn itself if it is a directory?

    Recursion pros and cons

    Often can solve a problem with recursion or with loops (an iterative solution). Why use recursion?

    Pros:

    • Short code
    • Clear code

    Unclear:

    • Speed

    Cons:

    • Uses more memory

    References

    Acknowledgements

    • Some of today's lecture was based on teaching materials developed for MCS 260 by Jan Verschelde.

    Revision history

    • 2020-10-24 Initial publication