Lecture 9 : OOPS Part 2 | Object Oriented Programming | Python Full Course

Shradha KhapraAbout 5 min readJun 30, 2025Watch original
THE SUMMARYAI-generated

Key Concepts

  • del keyword: Deletes object properties or the entire object.
  • Private attributes: Attributes intended for use only within the class, not accessible from outside.
  • Inheritance: A class deriving properties from another class.
  • Single Inheritance: One parent class and one child class.
  • Multilevel Inheritance: A class inherits from a derived class, which in turn inherits from a base class.
  • Multiple Inheritance: A class inherits from multiple base classes.
  • super() method: Used to access methods of the parent class.
  • Class methods: Methods bound to the class and receive the class as an implicit first argument (cls).
  • Static methods: Methods that do not access or modify class or instance state.
  • @property decorator: Allows a method to be used as a property (attribute).
  • Polymorphism: The ability of a single type (e.g., operator) to have different meanings depending on the context.
  • Operator overloading: A form of polymorphism where operators have different meanings based on the data types they operate on.

The del Keyword

The del keyword is used to delete object properties or the entire object from memory. Objects occupy memory space due to their methods and attributes. Unnecessary objects can be removed to free up memory.

  • Deleting Properties: del object.property
  • Deleting Objects: del object

Example:

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

s1 = Student("Shraddha")
del s1  # Deletes the s1 object
## print(s1.name)  # Raises an error because s1 is no longer defined

Private Attributes

Private attributes are intended for internal use within a class and should not be accessed directly from outside the class. This helps protect sensitive information and prevent accidental modification.

  • Naming Convention: Prefixing an attribute with double underscores (__) makes it "private."
  • Access: Private attributes can be accessed within the class methods but not directly from outside.

Example:

class Account:
    def __init__(self, account_number, account_password):
        self.account_number = account_number
        self.__account_password = account_password  # Private attribute

    def reset_password(self):
        print(self.__account_password)  # Accessible within the class

account1 = Account("12345", "ABCDE")
## print(account1.__account_password)  # Raises an error: no attribute 'account_password'
account1.reset_password()  # Prints the password because it's called from within the class

Important Note: Python's privacy is conceptual. The name mangling still allows access with _ClassName__attributeName.

Inheritance

Inheritance allows a class (child class or derived class) to inherit properties and methods from another class (parent class or base class). This promotes code reuse and establishes relationships between classes.

Example:

class Car:
    @staticmethod
    def start():
        print("Car Started")

    @staticmethod
    def stop():
        print("Car Stopped")

class ToyotaCar(Car):  # Inherits from Car
    def __init__(self, name):
        self.name = name

my_car1 = ToyotaCar("Corolla")
my_car1.start()  # Inherited method from Car
print(my_car1.name)

Types of Inheritance

  1. Single Inheritance: A class inherits from a single parent class.
  2. Multilevel Inheritance: A class inherits from a derived class, which in turn inherits from a base class.
    class Grandparent:
        def grandparent_method(self):
            print("Grandparent method")
    
    class Parent(Grandparent):
        def parent_method(self):
            print("Parent method")
    
    class Child(Parent):
        def child_method(self):
            print("Child method")
    
    c = Child()
    c.grandparent_method() # Output: Grandparent method
    c.parent_method() # Output: Parent method
    c.child_method() # Output: Child method
    
  3. Multiple Inheritance: A class inherits from multiple base classes.
    class A:
        variable_a = "Welcome to class A"
    
    class B:
        variable_b = "Welcome to class B"
    
    class C(A, B):  # Inherits from A and B
        variable_c = "Welcome to class C"
    
    c1 = C()
    print(c1.variable_a)  # Accessing variable_a from class A
    print(c1.variable_b)  # Accessing variable_b from class B
    print(c1.variable_c)  # Accessing variable_c from class C
    

The super() Method

The super() method is used to access methods of the parent class from within a child class. This is particularly useful for calling the parent class's constructor (__init__) to initialize inherited attributes.

Example:

class Car:
    def __init__(self, type):
        self.type = type

    @staticmethod
    def start():
        print("Car Started")

class NewCar(Car):
    def __init__(self, type):
        super().__init__(type)  # Calls the parent class's constructor
        super().start() # Calls the parent class's start method
        self.new_attribute = "New"

car1 = NewCar("Electric")
print(car1.type)  # Accessing the inherited attribute

Class Methods

Class methods are bound to the class and receive the class itself as the first argument (conventionally named cls). They are defined using the @classmethod decorator. Class methods can access and modify class-level attributes.

Example:

class Person:
    name = "Anonymous"  # Class attribute

    @classmethod
    def change_name(cls, new_name):
        cls.name = new_name  # Modifying the class attribute

print(Person.name) # Output: Anonymous
Person.change_name("Rahul Kumar")
print(Person.name) # Output: Rahul Kumar

Comparison of Method Types:

  • Instance Methods: Receive the instance (self) as the first argument; used to access and modify instance-specific data.
  • Class Methods: Receive the class (cls) as the first argument; used to access and modify class-level data.
  • Static Methods: Do not receive self or cls; used for utility functions that don't depend on class or instance state.

The @property Decorator

The @property decorator allows a method to be accessed like an attribute. This is useful when the value of an attribute needs to be calculated dynamically or when you want to encapsulate access to an attribute.

Example:

class Student:
    def __init__(self, physics, chemistry, math):
        self.physics = physics
        self.chemistry = chemistry
        self.math = math

    @property
    def percentage(self):
        return (self.physics + self.chemistry + self.math) / 3

student1 = Student(98, 95, 93)
print(student1.percentage)  # Accessing percentage as an attribute

student1.physics = 86  # Changing a value
print(student1.percentage)  # Percentage is automatically recalculated

Polymorphism and Operator Overloading

Polymorphism allows a single type (e.g., an operator) to have different meanings depending on the context. Operator overloading is a form of polymorphism where operators have different behaviors based on the data types they operate on.

Examples:

  • 1 + 2 (addition of numbers)
  • "Apna" + "College" (string concatenation)
  • [1, 2, 3] + [4, 5, 6] (list concatenation)

Operator Overloading in Custom Classes:

Python allows you to define how operators behave for your own classes by implementing special methods (e.g., __add__ for the + operator).

Additional Decorators (Homework):

  • Getter
  • Setter

Synthesis/Conclusion

This section covered advanced OOP concepts in Python, including memory management with del, data protection with private attributes, code reuse with inheritance, accessing parent class methods with super(), class-level operations with class methods, dynamic attribute calculation with @property, and flexible operator behavior with polymorphism. These concepts enable the creation of robust, maintainable, and extensible Python code.

AI summaries can miss context or contain errors. Check important details against the original video.

Go a little deeper.

Have a question about this video? Load its transcript to open the video chat.