basic_python/oop.rst
author Puneeth Chaganti <punchagan@fossee.in>
Sun, 06 Feb 2011 17:57:03 +0530
changeset 157 3174d4803cd5
parent 88 1e5c78018aa0
permissions -rw-r--r--
latex: Changes to slides and handout before and after class.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
53
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
     1
Classes and Objects
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
     2
===================
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
     3
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
     4
In the previous sections we learnt about functions which provide certain level
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
     5
of abstraction to our code by holding the code which performs one or more
88
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
     6
specific functionality. We were able to use this function as many times as we
53
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
     7
wanted. In addition to functions, Python also higher level of abstractions
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
     8
through *Classes* and *Objects*. *Objects* can be loosely defined as a
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
     9
collection of a set of data items and a set of methods. The data items can be
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    10
any valid Python variable or any Python object. Functions enclosed within a class
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    11
are called as *methods*. If you are thinking if methods are functions why is there
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    12
a distinction between the two? The answer to this will be given as we walk through
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    13
the concepts of *Classes* and *Objects*. *Classes* contain the definition for the
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    14
*Objects*. *Objects* are instances of *Classes*.
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    15
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    16
A class is defined using the keyword **class** followed by the class name, in
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    17
turn followed by a semicolon. The statements that a *Class* encloses are written
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    18
in a new block, i.e on the next indentation level::
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    19
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    20
  class Employee:
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    21
    def setName(self, name):
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    22
      self.name = name
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    23
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    24
    def getName(self):
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    25
      return self.name
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    26
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    27
In the above example, we defined a class with the name Employee. We also defined
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    28
two methods, setName and getName for this class. It is important to note the
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    29
differences between the normal Python functions and class methods defined above.
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    30
Each method of the class must take the same instance of the class(object) from
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    31
which it was called as the first argument. It is conventionally given the name,
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    32
*self*. Note that *self* is only a convention. You can use any other name, but
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    33
the first argument to the method will always be the same object of the class
88
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    34
from which the method was called. The data members that belong to the class are
53
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    35
called as *class attributes*. *Class attributes* are preceded by the object of
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    36
the class and a dot. In the above example, *name* is a class attribute since it
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    37
is preceded by the *self* object. *Class attributes* can be accessed from
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    38
anywhere within the class. 
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    39
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    40
We can create objects of a class outside the class definition by using the same
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    41
syntax we use to call a function with no parameters. We can assign this object
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    42
to a variable::
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    43
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    44
  emp = Employee()
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    45
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    46
In the above example, we create an object named *emp* of the class *Employee*.
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    47
All the attributes and methods of the class can be accessed by the object of the
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    48
class using the standard notation *object.attribute* or *object.method()*.
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    49
Although the first parameter of a class method is the self object, it must not
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    50
be passed as an argument when calling the method. The *self* object is implicitly
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    51
passed to the method by the Python interpreter. All other arguments passing rules
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    52
like default arguments, keyword arguments, argument packing and unpacking follow
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    53
the same rules as those for ordinary Python functions::
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    54
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    55
  >>> emp.setName('John')
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    56
  >>> name = emp.getName()
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    57
  >>> print name
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    58
  John
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    59
  >>> print emp.name
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    60
  John
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    61
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    62
If we at all try to access a class attribute before assigning a value to it, i.e
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    63
before creating it, Python raises the same error as it would raise for the
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    64
accessing undefined variable::
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    65
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    66
  >>> emp = Employee()
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    67
  >>> emp.name
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    68
  Traceback (most recent call last):
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    69
    File "class.py", line 10, in <module>
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    70
      print e.name
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    71
  AttributeError: Employee instance has no attribute 'name'
76facb1dc81b Added section for Classes and Objects.
Madhusudan.C.S <madhusudancs@gmail.com>
parents:
diff changeset
    72
88
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    73
It is also possible to assign values to the attributes using the above notation::
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    74
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    75
  >>> emp = Employee()
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    76
  >>> emp.name = 'John'
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    77
  >>> print emp.name
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    78
  John
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    79
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    80
Magic methods
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    81
-------------
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    82
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    83
Python reserves a number of names starting and ending with **__**. Note that it
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    84
is a double underscore. We must not invent names of this kind in our programs.
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    85
These methods are generally referred to as *Magic methods* or sometimes called
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    86
as *Special Methods*. Each *Magic method* performs a specific function. One such
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    87
magic method we will discuss now is **__init__** method. If you are from C++
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    88
background, the **__init__** method is analogous to the class constructor. This
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    89
method is called a constructor because, it is implicitly called everytime a new
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    90
instance of the class is created. So effectively **__init__** method constructs
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    91
the object from the class and sets up some initial values for the object. Other
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    92
than the above special properties, the **__init__** method is similar to any other
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    93
class method. The argument passing rules are same for **__init__** method. Although,
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    94
since **__init__** is called when the object is created we need to pass the
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    95
arguments to the class name we call while creating the object. It passes the
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    96
arguments to the **__init__** method::
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    97
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    98
  class Employee:
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
    99
    def __init__(self, name):
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   100
      self.name = name
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   101
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   102
    def getName(self):
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   103
      return self.name
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   104
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   105
  >>> emp = Employee('John')
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   106
  >>> print emp.getName()
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   107
  John
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   108
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   109
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   110
Writing Object Oriented Code
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   111
----------------------------
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   112
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   113
Object oriented code mainly encompasses three components: Encapsulation, Inheritence and Polymorphism.
1e5c78018aa0 Committing last changes.
Madhusudan.C.S <madhusudancs@gmail.com>
parents: 53
diff changeset
   114
Lets briefly look at each of them with examples.