1. OOPs, Concept

  • Object Oriented Programming
  • OOP is a specific way of designing a program by using classes and objects
  • It allows us to relate program with real-world objects, like properties and behaviors
  • Properties
    • It defines the state of the object.
    • Like: name, age, address etc. that store data of the object
  • Behaviors
    • Are the actions our object can take.
    • Like: talking, breathing, running etc
    • Oftentimes, this involves using or modifying the properties of our object.
# Example
DOOR CLASS

Properties:
  height
  color
  is_locked

Behaviors:
  open()
  closed()
  toggle_lock()

1.1 Class

  • Classes are used to create user-defined data structures.
  • It’s like a blueprint for an object where we define all its properties and behaviours
class className:
    ''' documenttation string '''
    variables: instance variables, static/class and local/method variables
    methods: instance methods,static methods,class methods

# Help
print(className.__doc__)
help(className)

1.2 Object

  • An Object is an instance of a Class it’s like a copy of the class.
  • Physical existence of a class is nothing but object. We can create any number of objects for a class.

Everything in Python is an object, and almost everything has attributes and methods

  • Properties –> Variables/Attribute
  • Behaviour –> Methods
class Employee:
  # Variable/Attribute
  raise_amount=1.04   	

  def __init__(self, name):
    self.name=name

  # Methods
  def user(self):
    print(self.name)

emp1=Employee('Amrit')
# Printing object's memory hex
print(emp1)

emp1.user()
# Amrit

1.3 Four pillars of OOPs

1. Encapsulation

  • It is used to restrict access to methods and variables.
  • Code and data are wrapped together within a single unit.
  • Access modifier are useful to attain encapsulation
  • It is achieved by access modifiers public, private, protected

2. Data Abstraction

  • Abstraction means hiding internal details and showing functionality
  • It can be achieved by using abstract classes and interfaces

3. Inheritance

  • It specifies that the child object acquires all the properties and behaviors of the parent object.
  • It provides re-usability of the code.

The new class is known as a derived class or child class, and the one whose properties are acquired is known as a base class or parent class.

Python Inheritance Terminologies

  • Superclass ors base class or parent class
    • The class from which attributes and methods are acquired.
  • Subclass or derived class or child class
    • The class which inherits the members from superclass.

Important Topics

  • Multiple Inheritance vs Multi-level Inheritance
  • Resolving the Conflicts with python multiple inheritance
  • Method Resolution Order (MRO)

4. Polymorphism

  • Poly means many. Morphs means forms.
  • Polymorphism means Many Forms

Yourself is best example of polymorphism. In front of Your parents You will have one type of behaviour and with friends another type of behaviour. Same person but different behaviours at different places, which is nothing but polymorphism.

  • Polymorphism can be achieved by
    • Method overriding
    • Method Overloading

Method overriding

  • Redefining the definitions (change the implementation) of methods in subclass which was already defined in superclass.
  • Following conditions must be met for overriding a function:
    • Inheritance should be there.
    • Function overriding cannot be done within a class.
    • The function that is redefined in the child class should have the same signature as in the parent class i.e. same number of parameters.

Method Overloading

  • We define a number of methods with the same name but with a different number of parameters as well as parameters can be of different types.
  • By default function overloading is not available in python
    • In symbol table, key is function name here.
    • Thus, when another function with same name is encountered, in symbol table current key value pair is overridden.

But by using decorator design pattern in python, function overloading can be implemented

@overload(int, int)
def area(length, breadth):
    pass

@overload(int)
def area(size):
    pass

1.4 Interface

In an interface all the methods are declared with an empty body.

Interfaces are not natively supported by Python, although abstract classes and abstract methods can be used to go around this.

# Informal Interface

class InformalInterface:
    def load_data(self):
        pass

class PdfReader(InformalInterface):
    def load_data(self):
        print('load data') 

1.5 Abstract class

A class that includes one or more abstract methods is referred to as an abstract class

An abstract method is one that is stated but does not have a concrete implementation; the implementation should be handled by a derived class.

We cannot create an abstract class in Python directly. However, Python does provide a module that allows us to define abstract classes. The module we can use to create an abstract class in Python is abc(abstract base class) module.

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def draw(self):
        pass

class Circle(Shape):
    def draw(self):
        print("Drawing a Circle")
    
circle = Circle()

Importance of Abstract Classes

We define a blueprint for our classes using an abstract class.

In Python if our subclasses don’t follow that blueprint, them python will give an error, which is very useful in complex projects involving large teams and a huge codebase

1.6 Inner classes

Sometimes we can declare a class inside another class, such type of classes are called inner classes.

Without existing one type of object if there is no chance of existing another type of object, then we should go for inner classes.

class Outer:
    def __init__(self):
        print("outer class object creation")
    class Inner:
        def __init__(self):
            print("inner class object creation")
        def m1(self):
            print("inner class method")
o=Outer()
i=o.Inner()
i.m1()

1.7 Garbage Collection

The main objective of Garbage Collector is to destroy useless objects. If an object does not have any reference variable then that object eligible for Garbage Collection. Garbage Collector always running in the background to destroy useless objects

By default, Garbage collector is enabled, but we can disable based on our requirement

# Returns True if GC enabled
gc.isenabled()

# To disable GC explicitly
gc.disable()

# To enable GC explicitly
gc.enable()

Relationships among classes

2 kind of relationships among classes

  • has a relation
    • Composition
      • Customer has-a Credit card
      • No existence of card without customer
    • Aggregation
      • Cart has-a Product
      • Product can exist without cart
  • is a relation
    • It an inheritance relation
    • ParkingLesson is a CarLesson
    • DrivingLesson is a CarLesson

Reference