Monday, January 20, 2014

Week Two

Re-Use and Recursion 

This week we learned how to define functions that can call themselves over again and again. For example, lets create a function that takes the sum of a list of numbers. Normally, using an accumulator I would do something like this:

def sum_list(L: list) -> float:
    """ Return the sum of the numbers in list L
    """
    sums = 0
    for x in L:
        sums += x
    return sums

What if we have nested lists inside other lists? Such as, L = [2, 3, [1, 5]] My original code will return a type error:

unsupported operand type(s) for +=: 'int' and 'list'
Obviously we can't add ints with lists... there must be another way.

def sum_list(L: list) -> float:
    """ Return the sum of the numbers in list L
    """

    return sum([sum_list(x) if isinstance(x, list) else x for x in L])

Let's take this step by step:
1. It checks if the first value of L is a list.
    a) if it is a list, it loops over each value in that list and takes the sum of their values.
    b) if it is a list and has another list inside it, it loops over the values in the inner list first. It takes the sums on     the inside before it moves on to the next value in the outer list.
    c) if it is not a list, it moves on to the next value in L.
2. Lastly, using the built-in: sum(), this takes the sum of the linear list.

Week One

Object-Oriented Programming:

Let's begin by creating our very own class. Something simple such as co-ordinates on the (x, y) plane. Thinking back to CSC108, I would do something like this:

class Point(object):
    """n-dimensional point
    """
 def __init__(self, x, y):
        """ (Point, float, float) - > NoneType
        Create a new point at x, y.
        """
    self.x = x
    self.y = y

Sweet. Now let's see how far it is from the origin by creating a new function.

def distance(self, x, y):
    """ Compute distance from the origin """
    return ((self.x ** 2) + (self.y ** 2)) ** 0.5

What if we have three points such as the Cartesian Plane (x, y, z). I guess we can go back and and self.z = z in the __init__ method. What if there is an infinite number, this seems like it's going to get painfully tedious. There must be another way...

class Point(object):
    """n-dimensional point
    """
    def __init__(self: "Point", coord: [float, ]) -> None:
        self.coord = [float(x) for x in coord]

Mind-blowing. Looks like gibberish at the moment.  ``Point`` is a type class that refers to self and [float, ] is a list of n variables.Using a for loop in the initializer, this lets us have a list of as many variables as we please.

list comprehensions --- [<expression> for x in iterable]

The new type contract helps us avoid __init__(self, x, y, z, ..., N):  Also, I'm not sure why but in the second contract, I get what looks like an invalid syntax error in WingIDE in the init method. Under the "-> None" , it looks something like this:

def __init__(self: "Point", coord: [float, ]) -> None: