Constructor:
In Python, a constructor is a special method that is automatically called when an object of a class is created. It is used to initialize the object's attributes with initial values. The constructor in Python is defined using the __init__
method.
class Employee:
def __init__(self, name, department,job, year):
pass
def work(self):
print("Working", self.empName, self.dept, self.desingnation,self.joining_year)
emp1 = Employee("guru", "B.Com", "Development", 2025)
emp2 = Employee("pritha", "M.E.,", "Design", 2025)
emp1.work()
AttributeError: 'Employee' object has no attribute 'empName'
We are trying to print instance variables like self.empName, self.dept, self.desingnation, and self.joining_year. However, these instance variables are not being initialized in the __init__
method.
class Employee:
def __init__(self, name, department,job, year):
self.empName = name
self.dept = department
self.designation=job
self.joining_year = year
def work(self):
print("Working", self.empName, self.dept, self.designation,self.joining_year)
emp1 = Employee("guru", "B.Com", "Development", 2025)
emp2 = Employee("pritha", "M.E.,", "Design", 2025)
emp2.work()
Working pritha M.E., Design 2025
self.empName = name: The parameter name is assigned to the instance variable empName. This means the employee's name will be stored in the empName attribute of the object.
Similarly, self.dept = department, self.designation = job, and self.joining_year = year store the values for the employee's department, job, and joining year, respectively
The work() method simply prints the employee's details (name, department, job, and joining year).
class Employee:
salary = 25000
def __init__(self, name, department,job, year):
self.empName = name
self.dept = department
self.desingnation=job
self.joining_year = year
def work(self):
print("Working", self.empName, self.dept, self.desingnation,self.joining_year)
print(self.salary)
def take_leave(self):
print(self.empName)
emp1 = Employee("guru", "B.Com", "Development", 2025)
emp2 = Employee("pritha", "M.E.,", "Design", 2025)
emp2.work()
emp1.take_leave()
Working pritha M.E., Design 2025
25000
guru
The salary is a class attribute, so if you want to access it within the work method, you need to access it from the class, either using self.salary or Employee.salary.
While you can use self.salary, it's important to understand that self refers to instance attributes, but since salary is a class attribute, accessing it via self is perfectly valid as well.
The take_leave() method is called for emp1 and prints the employee’s name.
class Employee:
def __init__(self, name, department,job, year):
self.name = name
self.department = department
self.job=job
self.year = year
emp1 = Employee("guru", "B.Com", "Development", 2025)
emp2 = Employee("pritha", "M.E.,", "Design", 2025)
print(emp1.__dict__)
print(emp2.__dict__)
{'name': 'guru', 'department': 'B.Com', 'job': 'Development', 'year': 2025}
{'name': 'pritha', 'department': 'M.E.,', 'job': 'Design', 'year': 2025}
The __dict__
attribute contains the attributes of the object, as well as their current values. It is a dictionary that maps the attribute names to their corresponding values.
Calling the class method directly on the class using decorator:
class Employee:
def __init__(self, name, department,job, year):
self.name = name
self.department = department
self.job=job
self.year = year
@classmethod
def credit_salary(cls):
print("Credit salary on last day of every month")
emp1 = Employee("guru", "B.Com", "Development", 2025)
emp2 = Employee("pritha", "M.E.,", "Design", 2025)
Employee.credit_salary()
Credit salary on last day of every month
The @classmethod decorator is used to define a method that is bound to the class, not the instance. The first parameter of the class method is cls, which refers to the class itself, not the instance.
We can call credit_salary() using Employee.credit_salary(), because it is a class method and can be accessed from the class itself.
Inner class:
The inner class has access to the outer class's attributes and methods, but it behaves as a separate class with its own namespace.
class College:
def __init__(self):
print("College Constructor")
class Dept:
def __init__(self):
print("Dept Constructor")
def work(self):
print("Working")
principal = College()
hod = principal.Dept()
hod.work()
College Constructor
Dept Constructor
Working
The Dept class is nested inside the College class, so it needs to be referenced as College.Dept when creating an instance of Dept outside the College class.
principal = College() initializes the College instance, and the constructor for College is called.
hod = College.Dept() creates an instance of the nested Dept class.
hod.work() calls the work method of the Dept class.
class SuperMarket:
def __init__(self, product_name, price, discount):
self.product_name = product_name
self.price = price
self.discount = discount
def buy(self):
print(self.product_name, self.price, self.discount)
product1 = SuperMarket("soap", 50, 10)
product2 = SuperMarket("Brush", 60,20)
product1.buy()
product2.buy()
soap 50 10
Brush 60 20
SuperMarket class with an__init__
method that accepts product_name, price, and discount as parameters.
product1 and product2 are instances of the SuperMarket class with their respective details.
The buy method prints the product_name, price, and discount for each product.
Constructor overloading:
In Python, constructor overloading is not directly supported. This is because Python does not allow multiple constructors with the same name.
However, you can achieve similar functionality by using default arguments or variable-length argument lists (e.g *args and **kwargs).
class SuperMarket:
def __init__(self, product_name, price, *discount):
self.product_name = product_name
self.price = price
self.discount = discount
def buy(self):
print(self.product_name, self.price, self.discount)
product1 = SuperMarket("soap", 50, 10)
product2 = SuperMarket("Brush", 60,20)
product3 = SuperMarket("Rice", 60)
product1.buy()
product2.buy()
product3.buy()
soap 50 (10,)
Brush 60 (20,)
Rice 60 ()
The *discount allows you to pass any number of discount values. If no value is provided for discount, it defaults to a tuple containing a single value 0.
If there are 3 arguments, it sets product_name, price, and discount.
If there are only 2 arguments, it assumes the discount is 0.
Inheritance:
Inheritance allows a class to inherit methods and properties from another class.
The class that inherits is called the child class (or subclass), and the class being inherited from is called the parent class (or superclass).
Types of Inheritance in Python:
There are five main types of inheritance in Python
Single Inheritance:In single inheritance, a child class inherits from one parent class.
Multiple Inheritance:In multiple inheritance, a class can inherit from more than one class.
Multilevel Inheritance:In multilevel inheritance, a class inherits from a class that is also a subclass of another class.
Hierarchical Inheritance:In hierarchical inheritance, multiple child classes inherit from a single parent class.
Hybrid Inheritance:Hybrid inheritance is a combination of multiple types of inheritance, such as a combination of multiple and multilevel inheritance.
class Shapes:
def find_area(self, side1, side2):
print(side1 * side2)
class Square(Shapes):
pass
s = Square()
s.find_area(5,5)
class Rectangle(Shapes):
pass
r = Rectangle()
r.find_area(10,8)
25
80
Both Square and Rectangle classes inherit from the Shapes class, which has the find_area method that calculates the area of a shape given two sides.
The Square class does not define its own find_area method but inherits it from the Shapes class. Therefore, calling s.find_area(5, 5) will calculate the area of a square with side length 5, which results in 5 * 5 = 25.
Similar to Rectangle class.
Example for multiple inheritance:
class Father:
def work(self):
print("Mechanical Engineer")
class Mother:
def work(self):
print("Software Engineer")
class Child(Father, Mother):
pass
child = Child()
child.work()
Mechanical Engineer
Multiple Inheritance in Python, where the Child class inherits from both Father and Mother. The Child class can access methods from both parent classes, but when you call child.work(), Python follows a method resolution order (MRO) to determine which method to execute.
Method Resolution Order(MRO):
In Python, when multiple classes are involved in inheritance, the MRO determines the order in which methods are called.
Child inherits from Father first, and then from Mother.
Therefore, Python will call the work method from the Father class (because it appears first in the inheritance list).
class Father:
def work(self):
print("Mechanical Engineer")
class Mother:
def work(self):
print("Software Engineer")
class Child(Mother, Father):
pass
child = Child()
child.work()
Software Engineer
If you want the Child class to inherit the work method from the Mother class, you can simply change the order of inheritance.
Method Overriding:
Method Overriding occurs when a subclass defines a method that has the same name, same parameters, and same return type as a method in its parent class. When the subclass calls this method, the method in the subclass overrides (replaces) the method in the parent class.
It is also called runtime polymorphism.
class Father:
def work(self):
print("Mechanical Engineer")
class Mother:
def work(self):
print("Software Engineer")
class Child(Mother, Father):
def work(self):
print("Business person")
child = Child()
child.work()
Business person
Overrides the work method and prints "Business person".
Since the Child class defines its own work method, the method from the Child class is called, regardless of the inheritance from Mother and Father.
Operator overriding:
Operator overloading allows you to define how operators like +, -, *, etc., should behave when they are used with instances of a class. In Python, this is done by defining special methods in your class, such as__add__, __sub__, __mul__
etc.
class Book:
def __init__(self, pages):
self.pages = pages
def __add__(self, second):
return self.pages + second.pages
book1 = Book(300)
book2 = Book(200)
print(book1 + book2)
500
__add__
method: This is the method that is called when the + operator is used between two Book objects. Inside this method, you're returning the sum of the pages attribute from both book1 and book2.
When you run print(book1 + book2), Python calls book1.__add__
(book2) behind the scenes, which adds the pages attribute from both books together and prints the result.
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def __mul__(self,other):
return self.salary * other.days
class TimeSheet:
def __init__(self, name, days):
self.name = name
self.days = days
emp = Employee("Pritha", 1000)
timesheet = TimeSheet("Pritha", 25)
print(emp * timesheet)
25000
When emp * timesheet is executed, Python internally calls emp.__mul__
(timesheet).
The __mul__
method multiplies the salary of the Employee object (emp) with the days from the TimeSheet object (timesheet).
Top comments (0)