CodingBison

Python supports object-oriented programming. It allows us to create objects, define their methods, and take advantage of object inheritance semantics. Python objects are based on a common template, known as a class. In general, a class is an aggregation of attributes (both data and functions). Object functions are also referred to as methods and typically they handle the data attributes.

To define a Python class, we can use the keyword "class" followed by the name of the class. Next, the class can define both variables (data attributes) and functions (methods). Definitions of class variables and methods form the class block. Python uses indentation to form a block -- all statements forming a block should have identical indentation.

Once a class has been defined, we can create an object by calling the name of the class like a function. An object created from a class is an instance of that class and it automatically acquires the attributes of that particular class.

Without further delay, let us get started with the implementation! We provide below an example that creates a class (bigCat) with both data attributes and a function attribute.

 [codingbison@localhost ~]$ python3
 Python 3.2.3 (default, Jun  8 2012, 05:40:06) 
 [GCC 4.6.3 20120306 (Red Hat 4.6.3-2)] on linux2
 Type "help", "copyright", "credits" or "license" for more information.
 >>> 
 >>> class bigCat:
 ...     def __init__(self, name, location, scientificName):
 ...         self.name = name
 ...         self.location = location
 ...         self.scientificName = scientificName
 ...     def returnLocation(self):
 ...         return self.location
 ... 
 >>> 

The above bigCat class has 3 data attributes: name, location, and scientificName. The class also has two methods, __init__() and returnLocation(). Method __init__() is the constructor method for this class and gets called internally when we create an object based on the class. We can pass arguments to the constructor and when an object is created, these values will be internally passed to the __init__() method. The returnLocation() method simply returns the location attribute of the class.

These data attributes and methods are available only as property of the class; in this regard, a Python class has a namespace of its own. Thus, if we were to access the variable "scientificName" outside the class, then that would be an error.

The above class-definition also uses the "self" keyword. This keyword represents the object instance that gets created from the class. We need to pass this keyword to the methods if we intend to access attributes of the object.

In addition, when we use the dir() function for "bigCat", it lists various attributes present with the class. This includes the returnLocation() method. Note that the dir() function does not return the data attributes like name, location, and scientificName attributes.

 >>> dir(bigCat)
 ['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', 
  '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', 
  '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
  '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'returnLocation']
 >>>

Now, let us go ahead and create an object ("objSnowLeopard") using the "bigCat" class. We pass various details of this object when we call the bigCat() class.

 >>> objSnowLeopard = bigCat("Snow Leopard", "Central Asia", "Panthera uncia")
 >>>
 >>> print(type(objSnowLeopard)) 
 <class '__main__.bigCat'>  
 >>> 
 >>> print(type(bigCat))
 <class 'type'>
 >>> 
 >>> dir(objSnowLeopard) 
 ['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', 
  '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', 
  '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
  '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 
  'location', 'name', 'returnLocation', 'scientificName']
 >>> 
 >>> print(objSnowLeopard)
 <__main__.bigCat object at 0xb73d5dac>
 >>> 

When we use the type() function for "bigCat" class, it returns the type as "type" but when we use the type for an instance of the object, then the type is printed as "<class '__main__.bigCat'>" -- this means that it is class with name bigCat and is defined in the __main__ module (which is the current module). Also, when we call the dir() function for the "objSnowLeopard", we see all the attributes of the object including the data attributes (name, location, and scientificName).

Like the case of other object-oriented programming languages, Python objects can be used to hold data (e.g. name, location, etc information about a big cat) and to implant useful methods (e.g. the returnLocation() method returns the location of the big cat). This allows us to simply pass these objects in different functions and as they pass from one function to another, they also carry along with them all the data and their methods.

Note that since arguments to Python functions are passed using (a copy of the) object reference, there is no copy involved, so even if the object contains a lot of data, it will not be inefficient. Another thing to note is that if we modify the object in the called function, then being the common reference, the object will also be modified once we return from the function.

Inheritance

Python allows the advantage of creating a new class on top of an existing class -- this capability is known as inheritance. The new class inherits all the data attributes and methods present in the parent class; in addition, it is free to add some of its own! This new class is referred to as a derived class and the base class is referred to as the parent class.

The derived class also inherits, among others, the constructor method of the parent class. However, if the derived class redefines its own constructor, then when we create an object from the derived class, it does not propagate to the parent's class constructor.

We provide a simple program to demonstrate inheritance. This program (provided below) defines a new class ("lion") that inherits a base class ("bigCat"). The "lion" class extends the parent class by adding two new data attributes ("prideName" and "hasMane") and a new method ("returnPrideName"). Since "lion" inherits "bigCat" class, it can automatically call the "returnLocation" method of the "bigCat" class without having to redefine it. This allows the derived class to simply focus on adding extra functionality and not have to worry about what is already offered by the parent class.

 >>> class bigCat:
 ...     def __init__(self, name, location, scientificName):
 ...         self.name = name
 ...         self.location = location
 ...         self.scientificName = scientificName
 ...     def returnLocation(self):
 ...         return self.location
 ... 
 >>> class lion(bigCat):
 ...     def __init__(self, name, location, scientificName, prideName, hasMane):
 ...         bigCat.__init__(self, name, location, scientificName)
 ...         self.prideName = prideName
 ...         self.hasMane = hasMane 
 ...     def returnPrideName(self):
 ...         return self.prideName
 ... 
 >>>

There are a few more things worth noticing in the above inheritance example. First, the derived class "lion" simply passes the earlier class "bigCat" in the class definition. Second, the __init__ method of the lion class takes two additional arguments: prideName and hasMane. Third, the __init__ method of the "lion" class calls the __init__ method of the bigCat first and then it assigns the passed prideName and hasMane arguments to the new data attributes of the lion class.

With that, let us create an object ("objLion") from the newly derived class "lion". Once we create the object, we can invoke not only its own defined method ("returnPrideName") but also the method ("returnLocation") of its parent class ("bigCat"). When we print the dir() output, we see that it shows data attributes and methods of not only the class "lion" but also of its parent class "bigCat".

 >>> objLion = lion("Lion", "Africa and Asia", "Panthera leo", "Cool Ones", True)
 >>> 
 >>> dir(objLion)
 ['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', 
  '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', 
  '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', 
  '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 
  '__weakref__', 
  'hasMane', 'location', 'name', 'prideName', 'returnLocation', 
  'returnPrideName', 'scientificName']
 >>> 
 >>> objLion.returnLocation()
 'Africa and Asia'
 >>> 
 >>> objLion.returnPrideName()
 'Cool Ones'
 >>> 




comments powered by Disqus