diff options
Diffstat (limited to 'lecture-notes/advanced-python/oop.rst')
-rw-r--r-- | lecture-notes/advanced-python/oop.rst | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/lecture-notes/advanced-python/oop.rst b/lecture-notes/advanced-python/oop.rst new file mode 100644 index 0000000..b1ecbe8 --- /dev/null +++ b/lecture-notes/advanced-python/oop.rst @@ -0,0 +1,230 @@ +Object Oriented Programming +=========================== + +At the end of this section, you will be able to - + +- Understand the differences between Object Oriented Programming and + Procedural Programming +- Appreciate the need for Object Oriented Programming +- Read and understand Object Oriented Programs +- Write simple Object Oriented Programs + +Suppose we have a list of talks, to be presented at a conference. How would +we store the details of the talks? We could possibly have a dictionary for +each talk, that contains keys and values for Speaker, Title and Tags of the +talk. Also, say we would like to get the first name of the speaker and the +tags of the talk as a list, when required. We could do it, as below. + +:: + + talk = {'Speaker': 'Guido van Rossum', + 'Title': 'The History of Python' + 'Tags': 'python,history,C,advanced'} + + def get_first_name(talk): + return talk['Speaker'].split()[0] + + def get_tags(talk): + return talk['Tags'].split(',') + +This is fine, when we have a small number of talks and a small number of +operations that we wish to perform. But, as the number of talks increases, +this gets inconvenient. Say, you are writing another function in some other +module, that uses this ``talk`` dictionary, you will also need to pass the +functions that act on ``talk`` to that function. This gets quite messy, +when you have a lot of functions and objects. + +This is where Objects come in handy. Objects, essentially, group data with +the methods that act on the data into a single block/object. + +Objects and Methods +------------------- + +The idea of objects and object oriented programming is being introduced, +now, but this doesn't mean that we haven't come across objects. Everything +in Python is an object. We have been dealing with objects all the while. +Strings, lists, functions and even modules are objects in Python. As we +have seen, objects combine data along with functions that act upon the +data and we have been seeing this since the beginning. The functions that +are tied to an object are called methods. We have seen various methods, +until now. + +:: + + s = "Hello World" + s.lower() + + l = [1, 2, 3, 4, 5] + l.append(6) + +``lower`` is a string method and is being called upon ``s``, which is a +string object. Similarly, ``append`` is a list method, which is being +called on the list object ``l``. + +Functions are also objects and they can be passed to and returned from +functions, as we have seen in the SciPy section. + +Objects are also useful, because the provide a similar interface, without +us needing to bother about which exact type of object we are dealing with. +For example, we can iterate over the items in a sequence, as shown below +without really worrying about whether it's a list or a dictionary or a +file-object. + +:: + + for element in (1, 2, 3): + print element + for key in {'one':1, 'two':2}: + print key + for char in "123": + print char + for line in open("myfile.txt"): + print line + for line in urllib2.urlopen('http://site.com'): + print line + +All objects providing a similar inteface can be used the same way. + +Classes +------- + +When we created a string ``s``, we obtained an object of ``type`` string. + +:: + + s = "Hello World" + type(s) + +``s`` already comes with all the methods of strings. So, it suggests that +there should be some template, based on which the object ``s`` is built. +This template or blueprint to build an object is the Class. The class +definition gives the blueprint for building objects of that kind, and each +``object`` is an *instance* of that ``class``. + +As you would've expected, we can define our own classes in Python. Let us +define a simple Talk class for the example that we started this section +with. + +:: + + class Talk: + """A class for the Talks.""" + + def __init__(self, speaker, title, tags): + self.speaker = speaker + self.title = title + self.tags = tags + + def get_speaker_firstname(self): + return self.speaker.split()[0] + + def get_tags(self): + return self.tags.split(',') + +The above example introduces a lot of new things. Let us look at it, piece +by piece. + +A class is defined using a ``class`` block -- the keyword ``class`` +followed by the class name, in turn followed by a semicolon. All the +statements within the ``class`` are enclosed in it's block. Here, we have +defined a class named ``Talk``. + +Our class has the same two functions that we had defined before, to get the +speaker firstname and the tags. But along with that, we have a new function +``__init__``. We will see, what it is, in a short while. By the way, the +functions inside a class are called methods, as you already know. By +design, each method of a class requires to have the same instance of the +class, (i.e., the object) from which it was called as the first argument. +This argument is generally defined using ``self``. + +``self.speaker``, ``self.title`` and ``self.tags`` are variables that +contain the respective data. So, as you can see, we have combined the data +and the methods operating on it, into a single entity, an object. + +Let's now initialize a ``Talk`` which is equivalent to the example of the +talk, that we started with. Initializing an object is similar to calling a +function. + +:: + + bdfl = Talk('Guido van Rossum', + 'The History of Python', + 'python,history,C,advanced') + +We pass the arguments of the ``__init__`` function to the class name. We +are creating an object ``bdfl``, that is an instance of the class ``Talk`` +and represents the talk by Guido van Rossum on the History of Python. We +can now use the methods of the class, using the dot notation, that we have +been doing all the while. + +:: + + bdfl.get_tags() + bdfl.get_speaker_firstname() + +The ``__init__`` method is a special method, that is called, each time an +object is created from a class, i.e., an instance of a class is created. + +:: + + print bdfl.speaker + print bdfl.tags + print bdfl.title + +As you can see, the ``__init__`` method was called and the variables of the +``bdfl`` object have been set. object have been set. Also notice that, the +``__init__`` function takes 4 arguments, but we have passed only three. The +first argument ``self`` as we have already seen, is a reference to the +object itself. + + +Inheritance +----------- + +Now assume that we have a different category for Tutorials. They are almost +like talks, except that they can be hands-on or not. Now, we do not wish to +re-write the whole code that we wrote for the ``Talk`` class. Here, the +idea of inheritance comes in handy. We "inherit" the ``Talk`` class and +modify it to suit our needs. + +:: + + class Tutorial(Talk): + """A class for the tutorials.""" + + def __init__(self, speaker, title, tags, handson=True): + Talk.__init__(self, speaker, title, tags) + self.handson = handson + + def is_handson(self): + return self.handson + +We have now derived the ``Tutorial`` class from the ``Talk`` class. The +``Tutorial`` class, has a different ``__init__`` method, and a new +``is_handson`` method. But, since it is derived from the ``Talk`` method it +also has the methods, ``get_tags`` and ``get_speaker_firstname``. This +concept of inheriting methods and values is called inheritance. + +:: + + numpy = Tutorial('Travis Oliphant', 'Numpy Basics', 'numpy,python,beginner') + numpy.is_handson() + numpy.get_speaker_firstname() + +As you can see, it has saved a lot of code duplication and effort. + +That brings us to the end of the section on Object Oriented Programming. In +this section we have learnt, + +- the fundamental difference in paradigm, between Object Oriented + Programming and Procedural Programming +- to write our own classes +- to write new classes that inherit from existing classes + +.. + Local Variables: + mode: rst + indent-tabs-mode: nil + sentence-end-double-space: nil + fill-column: 75 + End: |