I was working on a project where I needed to create several custom classes in Python. As I was building these classes, I realized how crucial the __init__ method is for proper object initialization. The __init__ method is one of Python’s special methods that plays a fundamental role in object-oriented programming.
In this article, I’ll cover everything you need to know about the __init__ method in Python – from basic usage to advanced techniques.
So let’s dive in!
What is the __init__ Method in Python?
The __init__ method (pronounced “dunder init” – short for double underscore init) is a special method in Python classes that gets called automatically when you create a new object from a class. It’s essentially the constructor method that initializes new objects.
Here’s a simple example:
class Customer:
def __init__(self, name, account_number):
self.name = name
self.account_number = account_number
self.balance = 0
# Creating a new customer
john = Customer("John Smith", "AC123456")In this example, when we create john, the __init__ method is automatically called with the arguments we provided, setting up the initial state of our customer object.
Why __init__ is Important
The __init__ method serves several critical purposes in Python:
- It initializes object attributes
- It ensures objects start in a valid state
- It simplifies object creation by handling setup tasks
- It enforces required parameters when creating objects
Basic Usage of __init__ Method in Python
Let me explain to you the methods for usage of the __init__ method in Python.
Method 1: Create Simple Initializers
The most common use of __init__ is to set up instance variables when an object is created:
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer = 0 # Default value
# Creating a car object
my_car = Car("Toyota", "Camry", 2023)
print(my_car.make) # Output: Toyota
print(my_car.odometer) # Output: 0I executed the above example code and added the screenshot below.

In this example, I’ve created a Car class that requires three parameters to initialize, and it also sets a default odometer value.
Method 2: Use Default Parameter Values
You can make some parameters optional by providing default values:
class Restaurant:
def __init__(self, name, cuisine_type, rating=4.0):
self.name = name
self.cuisine_type = cuisine_type
self.rating = rating
self.is_open = False
# Creating restaurants with and without specifying a rating
joes = Restaurant("Joe's Diner", "American")
fancy_place = Restaurant("Le Bistro", "French", 4.8)
print(joes.rating) # Output: 4.0
print(fancy_place.rating) # Output: 4.8I executed the above example code and added the screenshot below.

Here, I’ve made the rating parameter optional by giving it a default value of 4.0.
Advanced Usage of __init__ in Python
Let us learn some advanced usages of __init__ method in Python.
Method 3: Parameter Validation
A powerful use of __init__ is to validate input parameters:
class BankAccount:
def __init__(self, account_number, initial_balance):
if not isinstance(account_number, str):
raise TypeError("Account number must be a string")
if not account_number.startswith("ACT-"):
raise ValueError("Account number must start with 'ACT-'")
if initial_balance < 0:
raise ValueError("Initial balance cannot be negative")
self.account_number = account_number
self.balance = initial_balance
# This will work
account = BankAccount("ACT-12345", 100)
# These will raise exceptions
# account1 = BankAccount(12345, 100) # TypeError
# account2 = BankAccount("12345", 100) # ValueError
# account3 = BankAccount("ACT-12345", -50) # ValueErrorIn this example, I’m validating both the account number format and ensuring the initial balance is not negative.
Method 4: Use __init__ with Inheritance
When working with inheritance, the __init__ method plays a key role:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Employee(Person):
def __init__(self, name, age, employee_id, salary):
# Call the parent class's __init__ method
super().__init__(name, age)
# Add Employee-specific attributes
self.employee_id = employee_id
self.salary = salary
# Creating an employee
emp = Employee("Sarah Johnson", 32, "E12345", 75000)
print(emp.name) # Output: Sarah Johnson
print(emp.employee_id) # Output: E12345I executed the above example code and added the screenshot below.

Using super().__init__() allows us to call the parent class’s initializer before adding our own initialization code.
Method 5: Property Initialization with Getters and Setters
We can combine __init__ with properties for better encapsulation:
class Temperature:
def __init__(self, celsius=0):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("Temperature below absolute zero is not possible")
self._celsius = value
@property
def fahrenheit(self):
return (self._celsius * 9/5) + 32
@fahrenheit.setter
def fahrenheit(self, value):
self.celsius = (value - 32) * 5/9
# Using the class
temp = Temperature(25)
print(temp.celsius) # Output: 25
print(temp.fahrenheit) # Output: 77.0
temp.fahrenheit = 86
print(temp.celsius) # Output: 30.0I executed the above example code and added the screenshot below.

Here, I initialize the temperature in Celsius and provide properties to access or modify it in either Celsius or Fahrenheit.
Common Patterns and Best Practices
I will explain to you the common patterns and best practices.
Delegate to Other Methods
For complex initialization, you can delegate work to other methods:
class ShoppingCart:
def __init__(self, customer_id):
self.customer_id = customer_id
self.items = {}
self.created_at = self._get_current_time()
self._initialize_discounts()
def _get_current_time(self):
from datetime import datetime
return datetime.now()
def _initialize_discounts(self):
# Complex discount initialization logic
self.discounts = {"new_customer": 0.10} if self._is_new_customer() else {}
def _is_new_customer(self):
# Logic to check if this is a new customer
return True # Simplified for exampleThis pattern keeps the __init__ method clean while still handling complex initialization.
Use *args and **kwargs
For flexible initialization, you can use *args and **kwargs:
class ConfigurableWidget:
def __init__(self, widget_id, *args, **kwargs):
self.widget_id = widget_id
self.args = args
# Default settings
self.settings = {
"color": "blue",
"size": "medium",
"visible": True
}
# Update with any provided settings
self.settings.update(kwargs)
# Different ways to initialize
basic_widget = ConfigurableWidget("W1")
custom_widget = ConfigurableWidget("W2", color="red", size="large", animated=True)
print(basic_widget.settings) # Default settings
print(custom_widget.settings) # Custom settings including 'animated'This pattern allows for highly flexible object creation with any number of optional parameters.
Things to Avoid with __init__
There are a few common mistakes to avoid when working with __init__:
- Avoid lengthy operations: The
__init__method should be quick and focused on initialization, not complex processing. - Don’t return values: The
__init__method should not return anything (it implicitly returnsNone). - Avoid circular dependencies: Be careful not to create objects that depend on each other during initialization.
- Don’t override instance variables unintentionally: When using inheritance, make sure you’re not accidentally overriding important variables.
Understanding the __init__ method is crucial for writing good object-oriented Python code. It’s one of the first special methods you’ll encounter, and mastering it will improve your class designs significantly.
Whether you’re building simple data containers or complex application objects, proper initialization through __init__ ensures your objects start in a valid, usable state. This foundation makes the rest of your code more reliable and easier to work with.
You may like to read:
- Python Screen Capture
- How to read video frames in Python
- How to Check Python Version
- What Does // Mean in Python? (Floor Division with Examples)

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.