Object Oriented Programming (OOP) programming became popular with Java. Microsoft quickly followed-up with the C# language. Now, OOP concepts are available in many languages. Python inherits alot of these OOP attributes, but performs it in its usual pythonic minimalism. The concepts are the same, but much of the cruft, such as accessor modifiers, are limited, leaving an succinct and enjoyable object modeling experience.
Introduction
OOP deals with classes (blueprints) and objects (instances of blueprint). Relationships between these two include:
- encapsulation - refers to object state and hiding it from the outside, implemented with access modifiers such as public, protected, private
- inheritance - how a child class can inherit a parent class to utilise its properties and functions, python has two types
- multiple inheritance
- multilevel inheritance
- polymorphism - using the same functions on different classes
- abstractions - describe in simpler terms, such as inheritance hierarchy, where more abstract concepts are at the top and more concrete ideas, at the bottom, build upon their abstractions.
Object Creation and Class (Static) Variables
Both __new__
(Python defines this function for every class by default) and __init__
together forms a constructor.
class Example:
def __init__(self):
self.var = 'studytonight'
#creating object of the class Example
mutantObj = Example()
function __del__
is the counter-part of function __new__
If we had wanted to create a class-level variable, then we would place it between the class definition and class methods, and not using .self
. In other languages, the static
keyword would be used.
class Example:
var = None
def __init__(self):
Example.var = 'studytonight'
Static methods can be implemented using a Decorator, and not using self
as an argument.
class Shape:
@staticmethod
def info(msg):
# show custom message
print(msg)
print("This class is used for representing different shapes.")
Shape.info("Welcome to Shape class")
Welcome to Shape class
This class is used for representing different shapes.
Encapsulation
Python makes the use of underscores to specify the access modifier for a specific data member and member function in a class.
# defining a class Employee with public variables
class Employee:
# constructor
def __init__(self, name, sal):
self.name = name
self.sal = sal
# defining a class Employee
class Employee:
# constructor
def __init__(self, name, sal):
self._name = name # protected attribute
self._sal = sal # protected attribute
# defining class Employee
class Employee:
def __init__(self, name, sal):
self.__name = name # private attribute
self.__sal = sal # private attribute
If we want to access the private member variable, we will get an error.
emp = Employee("Bill", 10000)
emp.__sal
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-9-d9e08f1374dc> in <module>
1 emp = Employee("Bill", 10000)
----> 2 emp.__sal
AttributeError: 'Employee' object has no attribute '__sal'
Inheritance
Inheriting the property of multiple classes into one.
Multiple Inheritance
class A:
a = None
# functions of class A
class B:
b = None
# functions of class B
class C(A, B):
c = None
# class C inheriting property of both class A and B
# add more properties to class C
cls = C()
cls.a == cls.b == cls.c
True
Multilevel Inheritance
We inherit the classes at multiple separate levels. We have three classes A, B and C, where A is the super class, B is its sub(child) class and C is the sub class of B.
class A:
a = None
# properties of class A
class B(A):
b = None
# class B inheriting property of class A
# more properties of class B
class C(B):
c = None
# class C inheriting property of class B
# thus, class C also inherits properties of class A
# more properties of class C
cls = C()
print( issubclass(C,B) )
print( issubclass(C,A) )
True
True
Use issubclass(Child, Parent)
when verifying classes.
Method Overriding
Overriding is possible if:
- inheritance exists between a parent and child classes
- function that is redefined in the child class should have the same signature, i.e. same number of parameters.
class Animal:
# properties
multicellular = True
# Eukaryotic means Cells with Nucleus
eukaryotic = True
# function breathe
def breathe(self):
print("I breathe oxygen.")
# function feed
def feed(self):
print("I eat food.")
Let’s create a child class Herbivorous which will extend the class Animal:
class Herbivorous(Animal):
# function feed
def feed(self):
print("I eat only plants. I am vegetarian.")
In the child class Herbivorous we have overridden the method feed(). So now when we create an object of the class Herbivorous and call the method feed() the overridden version will be executed.
herbi = Herbivorous()
herbi.feed()
I eat only plants. I am vegetarian.
Polymorphism and Method Overloading
Method Overloading is a type of polymorphism in which we can define a number of methods with the same name but with parameters can be of different types. Similar to Overriding, it requires the same signature.
class Square:
side = 5
def calculate_area(self):
return self.side * self.side
class Triangle:
base = 5
height = 4
def calculate_area(self):
return 0.5 * self.base * self.height
def find_area_of_shape(obj):
print( obj.calculate_area() )
sq = Square()
tri = Triangle()
# calling the method with different objects
find_area_of_shape(sq)
find_area_of_shape(tri)
25
10.0
Abstractness
Abstract Classes
Abstract classes are classes that contain one or more abstract methods. An abstract method is a method that is declared, but contains no implementation. Abstract classes cannot be instantiated, and require subclasses to provide implementations for the abstract methods.
The following Python code uses the abc module and defines an abstract base class:
from abc import ABC, abstractmethod
class AbstractClassExample(ABC):
def __init__(self, value):
self.value = value
super().__init__()
@abstractmethod
def do_something(self):
pass
Must override the method; otherwise, it will error-out. A class that is derived from an abstract class cannot be instantiated unless all of its abstract methods are overridden.
class DoAdd42(AbstractClassExample):
def do_something(self):
return self.value + 42
x = DoAdd42(10)
print(x.do_something())
52
MetaClasses
Create classes like classes create objects. Important when classes should be configured based upon runtime specifications.