Python __init__ Method

Complete guide to Python's __init__ method covering object initialization, default values, inheritance, and best practices.

Python __init__ Method

Python init Method

Last modified April 8, 2025

This comprehensive guide explores Python’s init method, the special method responsible for object initialization. We’ll cover basic usage, inheritance, default values, multiple constructors, and practical examples.

Basic Definitions

The init method is a special method in Python classes that initializes newly created objects. It’s called automatically after the object is created by new.

Key characteristics: it must accept self as first parameter, doesn’t return anything, and is used to set initial values for object attributes. Unlike constructors in other languages, it doesn’t create the object.

Basic init Implementation

Here’s the simplest implementation showing how init initializes object attributes. This demonstrates the fundamental usage pattern.

basic_init.py

class Person: def init(self, name, age): self.name = name self.age = age

person = Person(“Alice”, 30) print(f"{person.name} is {person.age} years old")

This example creates a Person class with name and age attributes. The init method sets these values when a new instance is created.

The self parameter refers to the instance being initialized. Attributes are assigned to self to make them instance variables.

Default Parameter Values

init can use default parameter values to make some arguments optional while still allowing customization during initialization.

default_values.py

class Car: def init(self, make, model, year=2023, color=“black”): self.make = make self.model = model self.year = year self.color = color

def __str__(self):
    return f"{self.year} {self.make} {self.model} ({self.color})"

car1 = Car(“Toyota”, “Camry”) car2 = Car(“Ford”, “Mustang”, 2022, “red”) print(car1) print(car2)

This Car class has required make and model parameters, with optional year and color parameters that default to 2023 and “black” if not provided.

Default parameters make classes more flexible while reducing boilerplate code. They’re especially useful when most instances share common default values.

Inheritance and init

When using inheritance, init methods can be chained to properly initialize parent class attributes along with child class attributes.

inheritance.py

class Animal: def init(self, species): self.species = species

def __str__(self):
    return f"I am a {self.species}"

class Dog(Animal): def init(self, name, breed): super().init(“dog”) self.name = name self.breed = breed

def __str__(self):
    return f"{super().__str__()}, {self.name} the {self.breed}"

dog = Dog(“Rex”, “Labrador”) print(dog)

This example shows how to properly initialize parent class attributes using super().init(). The Dog class extends Animal while adding its own attributes.

The super() function returns a proxy object that delegates method calls to the parent class. This ensures proper method resolution order.

Multiple Constructors with @classmethod

While Python doesn’t support multiple constructors directly, you can simulate them using @classmethod to create alternative initialization methods.

multiple_constructors.py

class Rectangle: def init(self, width, height): self.width = width self.height = height

@classmethod
def from_square(cls, side_length):
    return cls(side_length, side_length)

@classmethod
def from_dict(cls, dimensions):
    return cls(dimensions['width'], dimensions['height'])

def area(self):
    return self.width * self.height

rect1 = Rectangle(4, 5) rect2 = Rectangle.from_square(3) rect3 = Rectangle.from_dict({‘width’: 2, ‘height’: 7}) print(rect1.area(), rect2.area(), rect3.area())

This Rectangle class shows three ways to create instances: through the standard init, via a square factory method, and from a dictionary of dimensions.

Class methods provide flexible initialization options while maintaining a single init method. Each factory method returns a new instance by calling the class constructor.

Initializing Collections in init

When initializing mutable collections as instance attributes, it’s important to create new collections for each instance to avoid shared state between instances.

collections_init.py

class ShoppingCart: def init(self, customer_name): self.customer_name = customer_name self.items = [] # New list for each instance

def add_item(self, item):
    self.items.append(item)

def __str__(self):
    return f"{self.customer_name}'s cart: {', '.join(self.items)}"

cart1 = ShoppingCart(“Alice”) cart2 = ShoppingCart(“Bob”) cart1.add_item(“Book”) cart2.add_item(“Shirt”) print(cart1) print(cart2)

This example demonstrates proper initialization of instance-specific collections. Each ShoppingCart gets its own empty list for items.

If the list was defined as a class variable instead, all instances would share the same list, leading to unexpected behavior when items are added.

Best Practices

  • Keep init simple: Focus on attribute initialization

  • Avoid complex logic: Move business logic to other methods

  • Use type hints: Document expected parameter types

  • Initialize all attributes: Set defaults for optional ones

  • Call super().init: In inheritance hierarchies

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.

ad ad