Thursday, February 27, 2014

Recursion

Recursion in computer science is the method of calling a function within it's own body. Recursion is used in programming when the solution to a problem involves knowing the solution of a simpler problem of the same kind. For example lets consider a simple function that returns the factorial of an integer n. This function could be implemented as follows:

def factorial(n):
    x = 1
    for i in range(1, n + 1):
        x = x * i
    return x

Here the function multiplies all integers from 1 to n and returns the result. But the function can also be implemented recursively as follows:


def factorial(n):
    return n * factorial(n - 1) if n > 0 else 1

Notice how the function now includes a call on itself in the body. The function here multiplies n with the factorial of n - 1 unless n is 0 in which case the function would return 1. Lets trace a few calls on this function:


>>> factorial(0)
# The if statement evaluates to false so the else clauseis returned
1
>>> factorial(1)
# The if statement evaluates to true so 1 is multiplied by factorial(0)
1
>>> factorial(2)
# 2 is multiplied by factorial(1)
2
>>> factorial(3)
# 3 is multiplied by factorial(2)
6

Now lets talk about the makeup of a recursive function. A recursive function contains a base case or a terminating case that breaks the chain of recursion. In the factorial function the base case would be when n is equal to 0 as no recursion occurred in the evaluation. All other cases are recursion cases where a chain of recursion runs until the base case is reached.

The function factorial could be implemented easily without having to use recursion as in the first implementation of the function above. However more elaborate recursive functions could be very difficult to implement without the use of recursion. For example a function that sums the numbers of a possibly nested list could be implemented easily using recursion which would otherwise be a challenging task. The function can be implemented as follows:


def sum_list(L: list) -> 'num':
    """
    Return the sum of the elements of L.
    
    >>> sum_list([1, 2, 3])
    6
    >>> sum_list([1, [2, 3, [4]], 5])
    15
    """
    return sum( # sum of sum of sublists or non-list elements themselves
        [sum_list(x) if isinstance(x, list) else x for x in L])

Finally recursion can also be used to define abstract data types. For example a Tree is an abstract data type that is made up of nodes connected to each other by edges where each node has only one parent. A tree consists of a root and possibly one or more children where each child is a tree itself. Another ADT that is based on recursion is a Linked list which is also made up of nodes where each node points to the next node in the list and each node contains a value. A linked list can either be an empty list or a node pointing to another linked list.

Wednesday, January 22, 2014

Object-Oriented Programming

Object-Oriented Programming revolves around representing concepts as objects. Objects have attributes to describe them and methods that can be used on them. Classes are used to create instances of a particular kind of object. Common examples of classes are str, int, tuple, float etc. The __init__ method is used to define attributes of an object. For example a class made to represent a point would have attributes x position and y position. Methods allow us to find information or change an object. Using the previous example, we could have methods such as distance from origin, distance between two points, midpoint between two points etc. In the case of the last method 'midpoint', the method returns an instance of the class point. By including the method __str__, you can create a string representation of an object, for example an appropriate representation of a point would be a tuple of the x and y coordinates (x, y). Inheritance is another key feature of Object-Oriented Programming. Inheritance allows a newly formed class to have access to all attributes and methods of a base class. This is very useful when creating a new class that is very similar to an existing with a few modifications. An object of a derived class will have all the attributes of the base class and could call any method from the base class. The function isinstance(obj, cla) checks wether an object obj belongs to class cla or a class that is derived from cla.