Skip to content

OOPs

  • Concept: A user-defined blueprint (Class) used to create specific data objects (Instances).

  • Methods & Syntax:

    • class ClassName: Defines the blueprint.
    • __init__(self, args): The constructor method. Automatically initializes the object’s initial state. self refers to the specific instance being created.
    • Class.variable: A class-level attribute shared across all instances.
    • self.variable: An instance-level attribute unique to that specific object.

    Program:

    class Employee:
    """Blueprint for Cloud Team members."""
    empCount = 0 # Class variable (shared)
    def __init__(self, role, salary):
    self.role = role # Instance variable (unique)
    self.salary = salary
    Employee.empCount += 1
    def displayEmployee(self):
    print(f"Role: {self.role}, Salary: {self.salary}")
    # Creating Instances
    emp1 = Employee("Cloud Intern", 200)
    emp2 = Employee("Cloud Manager", 5000)
    emp1.displayEmployee()
    emp2.displayEmployee()
    print(f"Total Employees: {Employee.empCount}")
    # Output:
    # Role: Cloud Intern, Salary: 200
    # Role: Cloud Manager, Salary: 5000
    # Total Employees: 2

  • Concept: Python allows you to dynamically add, read, modify, or delete attributes of an object after it has been instantiated.

  • Methods & Syntax:

    • hasattr(obj, 'name'): Returns True if the attribute exists.
    • getattr(obj, 'name'): Returns the value of the attribute.
    • setattr(obj, 'name', value): Sets or creates the attribute with the given value.
    • delattr(obj, 'name'): Deletes the attribute.

    Program:

    # Continuing with emp1 from above
    setattr(emp1, 'git_commits', 15) # Dynamically add an attribute
    if hasattr(emp1, 'git_commits'):
    print(getattr(emp1, 'git_commits')) # Outputs: 15
    delattr(emp1, 'git_commits') # Deletes the attribute
    # getattr(emp1, 'git_commits') # Would now raise AttributeError

3. Inheritance & Method Resolution Order (MRO)

Section titled “3. Inheritance & Method Resolution Order (MRO)”
  • Concept: A Child class extracts and reuses methods/properties from one or more Parent (Base) classes.

  • Methods & Syntax:

    • class Child(Base1, Base2):: Multiple inheritance syntax.
    • super().method(): Calls a method from the immediate parent class.
    • MRO Logic: Bottom-to-Top, Left-to-Right. Python checks the Child first, then Base1 (Left), then Base2 (Right).

    Program:

    class Base1:
    def execute(self):
    print("Executing Base1 script")
    class Base2:
    def deploy(self):
    print("Deploying from Base2")
    class Child(Base1, Base2):
    def execute(self):
    print("Executing Child script")
    super().execute() # Triggers Base1.execute due to MRO (Left parent)
    c = Child()
    c.execute()
    # Output:
    # Executing Child script
    # Executing Base1 script
    c.deploy()
    # Output: Deploying from Base2

4. “Private” Variables & Name Mangling

Section titled “4. “Private” Variables & Name Mangling”
  • Concept: Python does not have strict private variables. It uses naming conventions to protect data from accidental modification.

  • Methods & Syntax:

    • _variable: (Single underscore) Convention indicating a non-public implementation detail. Do not touch.
    • __variable: (Double underscore) Triggers Name Mangling. The interpreter renames it to _ClassName__variable to prevent subclass naming collisions.

    Program:

    class ServerCounter:
    __secretCount = 0 # Mangled variable
    def count(self):
    self.__secretCount += 1
    print(self.__secretCount)
    counter = ServerCounter()
    counter.count() # Output: 1
    counter.count() # Output: 2
    # print(counter.__secretCount) # Raises AttributeError
    print(counter._ServerCounter__secretCount) # Output: 2 (Bypassing the mangle)

5. Magic (Dunder) Methods & Operator Overloading

Section titled “5. Magic (Dunder) Methods & Operator Overloading”
  • Concept: Special internal methods enclosed in double underscores (__method__) that dictate how standard Python operators (+, , print) interact with your custom objects.

  • Methods & Syntax:

    • __str__(self): Dictates what is printed when you call print(object).
    • __add__(self, other): Dictates what happens when you use the + operator between two instances.

    Program:

    class Vector:
    def __init__(self, a, b):
    self.a = a
    self.b = b
    def __str__(self):
    # Overloads how the object represents itself as a string
    return f'Vector ({self.a}, {self.b})'
    def __add__(self, other):
    # Overloads the '+' operator logic
    return Vector(self.a + other.a, self.b + other.b)
    v1 = Vector(2, 10)
    v2 = Vector(5, -2)
    # Implicitly calls v1.__add__(v2), and then print() implicitly calls __str__
    print(v1 + v2)
    # Output:
    # Vector (7, 8)