Key Concepts
delkeyword: 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.
@propertydecorator: 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
- Single Inheritance: A class inherits from a single parent class.
- 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 - 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
selforcls; 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.





