1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
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:
|