Published: 27 Nov 2025 | Reading Time: 4 min
__init__ initializes an object; __new__ creates the object before __init__ runs*args, **kwargsPython is an object-oriented programming language, and one of the most fundamental concepts in OOP is the use of a constructor. A Python constructor is a unique class method used for initializing an object. When the object of a class is being created, its constructor is implicitly called to start the class instance variables.
In this article, we will discuss constructors in Python, their types, efficient usage, and a few advanced concepts, such as multiple constructors, instance methods, and the difference between the init and new methods.
A constructor is a special function that is called when an object of a class is created. It initializes the attributes of an object and prepares the object for use. The class constructor in python is always named __init__, and it is called automatically whenever an object is created.
Here is the syntax of a constructor in python:
class ClassName:
def __init__(self, parameter1, parameter2): # Constructor
self.attribute1 = parameter1 # Initialization of Attribute1
self.attribute2 = parameter2 # Initialization of attribute2
Here is an example to create a constructor in python:
class P:
def __init__(self, name, age):
self.name = name
self.age = age
# Creating an object
P1 = P("Deepthi", 22)
print(P1.name)
print(P1.age)
__init__(self, name, age) that initializes two attributes by name and ageP("Deepthi", 22), it initializes "Deepthi" to name and 22 to ageprint(P1.name) will output the name property of P1, i.e., "Deepthi"print(P1.age) statement prints the age parameter of P1, which is 22Deepthi
22
Here is an example to count the objects of class in python:
class Counter:
count = 0
def __init__(self):
Counter.count += 1
obj1 = Counter()
obj2 = Counter()
print(Counter.count) # Output: 2
__init__ increases the count variable by 1 every time an object is created from the Counter classprint(Counter.count) will display 2 since two objects were created and added to the counter variable2
__init__ is automatically called during object creationThe constructor method in python are utilised to initialise class objects. They are invoked through the __init__ method. There are two types of constructors in Python:
A default constructor does not accept any argument except self. It initialises an object by passing no initial values for object attributes.
If a constructor is not defined in a class, Python also offers a default constructor that can utilize default values for initializing the object.
class Person:
def __init__(self):
self.name = "Deepthi"
self.age = 22
p = Person()
print(p.name)
print(p.age)
__init__ method, which is the constructor. The constructor here is not supplied with any parameters other than selfp = Person() is executed, the constructor is called and an object p of type Person is createdDeepthi
22
The non-parameterized constructor can also be stated as a default constructor since it does not have any parameters but self. It is useful when you're creating objects with default values of attributes.
class Car:
def __init__(self):
self.make = "Toyota"
self.model = "Corolla"
car1 = Car() # Non-parameterized constructor is invoked
print(car1.make) # Output: Toyota
car1 = Car() is called, the constructor is called and an object Car is made using the default make and model valuesToyota
A parameterized constructor that takes one or more parameters to set the object with particular values when the object is created. This enables you to create an object with personalized attributes.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person2 = Person("Deepthi", 22) # Parameterized constructor is called
print(person2.name) # Output: Deepthi
__init__ with two arguments, name and age, and selfperson2 = Person("Deepthi", 22) is executed, the constructor is called with arguments passed "Deepthi" for name and 22 for ageDeepthi
Instance methods act on an instance of the class and access or change its attributes. They always have self as their first parameter.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f"Hello, my name is {self.name} and I am {self.age} years old.")
# Creating an object of Person
person1 = Person("Deepthi", 22)
# Calling the instance method
person1.greet()
__init__ method to set up the name and age attributesHello, my name is Deepthi and I am 22 years old.
*args, or **kwargsThe constructor cannot be overloaded in Python. You can define several __init__() instances within one class, and the last one will replace the previous ones. To achieve the effect of overloading the constructors, you may use default argument lists or class methods.
class Student:
def __init__(self):
print("First Constructor")
def __init__(self):
print("Second Constructor")
# Creating an object
st = Student()
__init__ methods, but Python will use the second one. This is because the last declared method with the same name in Python will override others__init__() is invoked, which prints "Second Constructor"Second Constructor
Python allows some built-in functions to be used on class attributes. A few of them are:
class Employee:
def __init__(self, name, emp_id, salary):
self.name = name
self.emp_id = emp_id
self.salary = salary
e = Employee("Deepthi", 102, 100000)
print(getattr(e, 'name'))
# Changing the value of 'salary'
setattr(e, "salary", 150000)
print(getattr(e, 'salary'))
# Checking if 'emp_id' attribute exists
print(hasattr(e, 'emp_id'))
# Deleting 'salary' attribute
delattr(e, 'salary')
try:
print(e.salary)
except AttributeError as error:
print(error)
getattr(e, 'name') returns the name attribute of e and prints "Deepthi"setattr(e, 'salary', 150000) sets e's salary to 150000 and prints the new valuehasattr(e, 'emp_id') is checking whether attribute emp_id exists in e and gives Truedelattr(e, 'salary') removes the salary attribute from e. Accessing it throws an AttributeError, which is trapped and printedDeepthi
150000
True
Error: 'Employee' object has no attribute 'salary'
Built-in attributes of Python classes provide information about the class:
__dict__: Gives the namespace of the class__doc__: It is a string that is used to store the documentation of the class__name__: The class name__module__: The module from which the class is imported__bases__: A tuple of parent classes of the classclass Employee:
def __init__(self, name, emp_id, age):
self.name = name
self.emp_id = emp_id
self.age = age
def display_details(self):
print(f"Name: {self.name}, Employee ID: {self.emp_id}, Age: {self.age}")
# Creating an employee object
e = Employee("Deepthi", 102, 22)
print(e.__doc__)
print(e.__dict__)
print(e.__module__)
e.__doc__ returns the docstring of the class, giving documentation of the Employee class and how to use ite.__dict__ returns the instance attribute dictionary (name, emp_id, age) and their valuese.__module__ returns the module name where the class was definedNone
{'name': 'Deepthi', 'emp_id': 102, 'age': 22}
__main__
Use getattr, setattr, and hasattr for dynamic access. Built-in attributes provide meta-information for classes.
__init__ and __new__ MethodsHere are the key differences for __init__ and __new__ methods:
__init__ |
__new__ |
|---|---|
__init__ is invoked when the object is being initialized. It is invoked after the object is already initialized. |
__new__ is tasked with creating a new object. It is invoked prior to __init__. |
__init__ is invoked after object creation. |
__new__ is invoked prior to __init__ in order to construct the object. |
__init__ has no return value (returns None implicitly). It modifies the object's state. |
__new__ is required to return a new object, typically by calling its parent class's __new__ method. |
| It modifies the object after the object has already been created. | It has to create the object itself, and not modify the object. |
__init__ takes self and additional parameters for initialization. |
__new__ takes cls (the class type) and typically returns an instance of the class (or subclass). |
| Used to set the initial state (attributes) of the object after it has been created. | Used to control how objects are created, such as when overriding object creation for custom behaviour. |
Besides the regular object creation with init(), Python offers sophisticated methods that lead to an advanced constructor usage. With these methods, it's possible to manage complicated situations e.g. inheritance from immutable built-in types, changing the process of object creation, and using design patterns such as singletons. Being skilled in these ideas makes your code cleaner, more modular, and gives you more freedom in your class design.
Immutable types (like int, float, str, and tuple) require that their values be set at creation, not after. To customize these types, override the new() method rather than init().
Example: Subclassing float with an extra attribute
class Distance(float):
def __new__(cls, value, unit):
obj = super().__new__(cls, value)
obj.unit = unit
return obj
# Creating an instance
d = Distance(10.5, "km")
# Accessing the values
print(d) # Output: 10.5
print(d.unit) # Output: km
Explanation:
By customizing new(), you can return an instance of a different class, turning your class into a flexible factory or enforcing custom object creators.
Example: Factory-like object creation
class Cat:
def __init__(self):
self.type = "Cat"
class Dog:
def __init__(self):
self.type = "Dog"
import random
class Pet:
def __new__(cls):
return random.choice([Cat(), Dog()])
pet = Pet()
print(pet.type) # Output: "Cat" or "Dog"
Explanation:
A singleton class ensures only one instance exists. This is achieved by controlling instance creation in new().
Example: Singleton pattern
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
# Testing the Singleton
a = Singleton()
b = Singleton()
print(a is b) # Output: True
Explanation:
Python is not capable of standard constructor overloading but you can imitate it by using default arguments or args and **kwargs in init(). In this way, the initialization parameters become flexible and both default constructors and parameterized constructors are supported.
Example: Flexible constructor
class Rectangle:
def __init__(self, width, height=None):
if height is None:
self.width = self.height = width
else:
self.width = width
self.height = height
# Creating instances
r1 = Rectangle(5)
r2 = Rectangle(4, 6)
# Printing dimensions
print(r1.width, r1.height) # Output: 5 5
print(r2.width, r2.height) # Output: 4 6
As a consequence of delving into such advanced constructor methods—using init() and new(), allowing modular code, and making custom object creators—you are able to manage complicated situations like subclassing immutable types, instance returning of a different class, and singleton class enforcement. These designs elevate the code readability and adaptability aspects, thus, your Python classes turn out to be more efficient and sustainable.
In Python's object-oriented programming, the self parameter plays a crucial role in constructors and class methods. It acts as a reference to the object being created or manipulated, allowing you to access and customize instance variables for each object.
class Person:
def __init__(self, name, age):
self.name = name # Attribute customization
self.age = age
p = Person("Deepthi", 22)
print(p.name) # Output: Deepthi
print(p.age) # Output: 22
Explanation:
By understanding and correctly using the self parameter, you enable powerful attribute customization, proper object creation, and maintain the core principles of object-oriented programming such as abstraction and inheritance.
The self is essential for instance-specific behavior. Advanced constructors enable singletons, factories, and subclassing immutable types.
Thinking through the use of constructors is one of the things that help writing Python code which can be maintained and understood easily. In short, while working with default constructors and custom initialization logic, you should follow the best practices presented below and also be aware of mistakes that you should not make.
By following these best practices and avoiding common mistakes, you can write constructors that enhance code readability, maintainability, and consistency—while keeping overhead low, especially for simple classes.
Constructors are the main tools involved in creating new objects in Python. Through a default constructor, a parameterized constructor, or a non-parameterized constructor, one can manage the way objects are set up and even guarantee that they are initially configured correctly. Still, while constructors offer a lot of positive features, they have some disadvantages as well, which should be taken into account in everyday programming.
If you comprehend absolutely the pros and cons of constructors, for instance, how can encapsulation, attribute validation, and design patterns like singletons help, while the risks of code complexity and difficulties in inheritance scenarios being among the drawbacks, you will be able to make better decisions when it comes to class organization.
Constructors make the process of creating objects faster, they initiate the objects in a consistent way, and they are compatible with OOP principles, however, you should not complicate your class or create unnecessary overhead if it is a simple class.
In conclusion, constructors in Python are significant when it comes to object initialization and setting their default state. Constructors provide the advantages of default as well as parameterized initialization of object attributes. Knowing how a constructor works and how __new__ and __init__ are distinct will aid you in constructing more efficient and useful Python classes.
It is very important for one to understand constructors in Python since that is the way they guarantee that objects are properly brought to life with the right attributes, they abide by the basic principles of OOP such as encapsulation and abstraction, they allow inheritance and also enable the use of advanced design patterns like singletons or factory methods that in the end lead to the improvement of code reliability, readability, and maintainability.
__init__ and __new__ differencesA Python constructor is a special method that is automatically called when an object of a class is instantiated. A constructor is applied to initialize the object's attributes (variables). Python constructs are implemented by using the __init__() method.
__init__ a Python constructor?Yes, __init__() is a Python constructor function. It gets invoked when a new object of a class is being instantiated. The __init__() function is used to set up the state and properties of the object. The __init__() function has self as its first argument (which is an instance of the class) and can have additional arguments to initialize the object with values.
__init__ in Python class?The __init__() method is a special method (a dunder method, short for "double underscore") used as the constructor in Python. It is automatically invoked when an object of a class is instantiated. Its main task is to initialize the object's attributes with values or to execute any setup that the object might required.
__init__ in Python?The __init__() function in Python is used to initialize objects with certain values at the time they are being created. Without __init__, the object would not be created in its desired state, and the class would use default values. The __init__() function has the possibility of creating more readable and flexible code.
Source: NxtWave - CCBP Blog
Original URL: https://www.ccbp.in/blog/articles/constructors-in-python