A class is a blueprint for creating objects, defining attributes (data) and methods (functions). Syntax: class ClassName:.
An object is an instance of a class, created to access its attributes and methods. Creation: obj = ClassName().
Use Case: Modeling real-world entities (e.g., employees, cars) with reusable code.
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def display_info(self):
return f"Name: {self.name}, Salary: ${self.salary}"
# Creating objects
emp1 = Employee("Krishna", 60000)
emp2 = Employee("Kristal", 55000)
# Accessing methods
print(emp1.display_info())
print(emp2.display_info())
Note: Employee is the class; emp1 and emp2 are objects. __init__ initializes object attributes.
Definition: A special (magic) method called a constructor, automatically invoked when an object is created.
Syntax: def __init__(self, *args, **kwargs):.
Purpose: Initializes instance variables for the object.
Use Case: Setting up initial state (e.g., name, ID) for objects.
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def car_info(self):
return f"Car: {self.brand} {self.model}"
# Creating objects with __init__
car1 = Car("Toyota", "Camry")
car2 = Car("Honda", "Civic")
print(car1.car_info())
print(car2.car_info())
Note: __init__ sets brand and model for each Car object. self refers to the instance being created.
Instance Variables: Unique to each object, defined in __init__ or other methods using self. Example: self.name.
Class Variables: Shared across all instances of a class, defined directly in the class body. Example: company_name shared by all Employee objects.
Use Case: Instance variables for object-specific data; class variables for shared data.
class Employee:
company_name = "TechCorp" # Class variable
def __init__(self, name, salary):
self.name = name # Instance variable
self.salary = salary # Instance variable
def info(self):
return f"{self.name} at {self.company_name}, Salary: ${self.salary}"
# Creating objects
emp1 = Employee("Krishna", 60000)
emp2 = Employee("Kristal", 55000)
print(emp1.info())
print(emp2.info())
# Modifying class variable
Employee.company_name = "NewTech"
print(emp1.info()) # Reflects updated class variable
Note: company_name is shared; name and salary are unique per object. Changing company_name affects all instances.
Inheritance: A class (child) inherits attributes and methods from another class (parent). Syntax: class ChildClass(ParentClass):.
Method Overriding: Child class provides a specific implementation of a parent class method. Access parent with super().
Use Case: Reusing and extending code (e.g., specialized employee types).
class Person:
def __init__(self, name):
self.name = name
def describe(self):
return f"Person: {self.name}"
class Employee(Person):
def __init__(self, name, salary):
super().__init__(name)
self.salary = salary
def describe(self): # Override parent method
return f"Employee: {self.name}, Salary: ${self.salary}"
# Creating objects
person = Person("Krishna")
employee = Employee("Kristal", 55000)
print(person.describe())
print(employee.describe())
Note: Employee inherits from Person; super().__init__ calls parent's constructor. describe is overridden in Employee.
Polymorphism: Objects of different classes can be treated as instances of a common parent class, using shared method names differently. Example: Multiple classes with a describe method.
Encapsulation: Restricting access to data and methods, typically using private attributes (_ or __). Single underscore: advisory protection; double underscore: name mangling.
Use Case: Polymorphism for flexible interfaces; encapsulation for data protection.
class Employee:
def __init__(self, name, salary):
self.name = name
self.__salary = salary # Private attribute
def describe(self):
return f"Employee: {self.name}"
def get_salary(self):
return self.__salary
class Manager(Employee):
def describe(self): # Polymorphic method
return f"Manager: {self.name}"
# Polymorphism
employees = [Employee("Krishna", 60000), Manager("Kristal", 80000)]
for emp in employees:
print(emp.describe())
# Encapsulation
emp = Employee("Ram", 55000)
print(f"Salary via getter: ${emp.get_salary()}")
Note: Polymorphism: describe behaves differently for Employee and Manager. Encapsulation: __salary is private, accessed via get_salary.
Class Methods: Operate on the class itself, using @classmethod. Syntax: def method(cls, *args). First parameter is cls.
Static Methods: Utility functions within a class, using @staticmethod. Syntax: def method(*args). No self or cls.
Use Case: Class methods for alternative constructors; static methods for utility functions.
__init__ for instance variable initialization.Employee.company).super() to extend parent functionality. Ensure overridden methods align with parent interface.__ for private attributes; provide getters/setters.@classmethod for alternative constructors or class-level logic. Use @staticmethod for utility functions not needing instance/class access.__str__ for readable object representation. Ensure magic methods return expected types (e.g., int for __len__).