Monday, January 27, 2014

Exceptions Part 1

During the last week, I was able to get a much better understanding of Exceptions, and how they worked.
When Danny first threw this chunk of code at us:

class SpecialException(Exception):
    pass

class ExtremeException(SpecialException):
    pass

if __name__ == '__main__':
    try:
        #1/0
        #raise SpecialException('I am a SpecialException')
        #raise Exception('I am an Exception')
        raise ExtremeException('I am an ExtremeException')
        1/0
    except SpecialException as se:
        print(se)
        print('caught as SpecialException')
        raise
    except ExtremeException as ee:
        print(ee)
        print('caught as ExtremeException')
        #raise
    except Exception as e:
        print(e)
        print('caught as Exception')

I had no idea what was happenng.

But I slowly worked it out after reading all of this week's readings and talking to Danny during his office hour.
Python already has many built in exceptions that are raised when certain situations arise, such as TypeError, or ValueError. This will end the code at that point, unless the exception is "caught". 

To catch an exception, we need a try/except clause. We tell the code to try certain values or operations, and if they work, the code will finish up normally and return what it's suppose to.
However, if the user were to input something that the code wasn't expecting, the program will raise an exception and stop running. If we want to prevent this abrupt termination, we can mitigate the exception by providing "solutions" for when these exceptions happen.
This is done with an except statement that follows try. The statement can be vague and not specify a type of exception, so that any exception that is raised will be caught by this statement. Alternatively, if many different problems can occur within the body of a function, we can set up numerous except clauses that filter the exceptions passed to them, and execute only when they're needed. Personally, I feel that this keeps the code shorter, simpler, and more organized, as well as allowing flexibility for the coder.

Going back to the above example that was brought up in lecture, I'm going to run through it with you. Please correct me if I'm wrong!

When ExtremeException is raised, any code left over after it (i.e 1/0) is never executed. The exception is caught by except SpecialException. Notice that ExtremeException is a subclass of SpecialException, but nothing was changed. This means that ExtremeException inherited all of its base class's behaviours, and can be caught by a SpecialException except clause.

Here's a curious question for you readers:
Since ExtremeException inherited all features of its parent class, does this include the __init__ function? If so, what type of exception is ExtremeExeption? Is it of class SpecialException, subclass ExtremeException?

Sunday, January 19, 2014

Object-Oriented Programming

When I first started CSC148, object-oriented programming was a familiar concept with an unfamiliar name, and I had some trouble putting the two together. The prerequisite CSC108 class taught me the foundation for the new material in this course, but I came out of CSC108 not completely understanding Classes.

Primarily, I didn't comprehend how the __init__ function worked, and especially how to set up attributes. I didn't know what self.x = x meant, or that it was possible to set up attributes without making them parameters in the constructor function.
To sum it up, I panicked a little when Danny pulled up Classes in our first lecture.

Since then, I've learned that __init__ basically sets up the class object, and gives it the "default settings" - the attributes. self.x = x creates instance variables for the object, and the __init__ function can even be omitted if it had no attributes (a surprising fact I learned in Exercise 1).

What really helped me to get a grasp of Classes was reading How to Think Like a Computer Scientist: Learning with Python. The section on Classes and Objects was clear and descriptive, and the way it was written was easy to understand. A particular explanation I thought was interesting was:

" The original syntax for a function call, print_time(current_time), suggests that the function is the active agent. It says something like, “Hey, print_time! Here’s an object for you to print.”
In object-oriented programming, the objects are considered the active agents. An invocation like current_time.print_time() says “Hey current_time! Please print yourself!”"