Constructors In Python — PBA Institute Tutorial
Chapter 18 · Python Programming Series
12 min read Beginner

Object Initialisation With Constructors

A constructor is the special method Python runs automatically when you create a new object. In Python it is called __init__. This chapter shows you the full life-cycle of an object, the role of __new__ and __init__, default and parameterised constructors, and the patterns professional developers use to initialise objects safely.

Overview

🚀

Auto-Triggered

Runs the moment you create an instance — no extra call needed.

🛠️

Custom State

Set all needed attributes in one place.

🎚️

Defaults

Accept optional arguments with default values.

🧬

Parent Calls

super().__init__() chains construction up the hierarchy.

🛡️

Validation

Reject bad input early — raise exceptions inside the constructor.

Syntax

  • Define with def __init__(self, ...):.
  • Python calls it automatically when you do obj = MyClass(args).
  • Use self.attribute = value to set instance state.
  • Use super().__init__() to invoke a parent class constructor.
Constructors — Syntax
class Person:
    def __init__(self, name, age=0):
        self.name = name
        self.age = age

class Employee(Person):
    def __init__(self, name, age, salary):
        super().__init__(name, age)
        self.salary = salary

emp = Employee("Riya", 25, 50000)
print(emp.name, emp.age, emp.salary)

Detailed Explanation

  • Why constructors matter: Constructors guarantee every new object starts in a valid state. They eliminate the need to manually set attributes after creation.
  • Default constructor: If you don't define __init__, Python provides a no-arg default that does nothing extra.
  • Parameterised constructor: Accepts arguments and assigns them to self. Most real classes have one.
  • Default values: Provide defaults in the signature: def __init__(self, x=0, y=0). Optional, named, and clean.
  • super().__init__(): In a subclass, call the parent constructor to inherit its initialisation. Forgetting this is a common bug.
  • __new__ vs __init__: __new__ creates the object (rare to override). __init__ initialises it (you override this constantly).

Code Examples

Example 1 — Default vs Parameterised
class Greeting:
    def __init__(self, name="World"):
        self.name = name
    def hello(self):
        return f"Hello, {self.name}!"

print(Greeting().hello())
print(Greeting("PBA").hello())
Output Hello, World!
Hello, PBA!
Example 2 — Constructor with Validation
class Age:
    def __init__(self, value):
        if value < 0:
            raise ValueError("Age cannot be negative")
        self.value = value

try:
    a = Age(-5)
except ValueError as e:
    print(e)
Output Age cannot be negative
Example 3 — Counting Instances
class Widget:
    count = 0
    def __init__(self, label):
        Widget.count += 1
        self.id = Widget.count
        self.label = label

for lbl in ["A", "B", "C"]:
    print(Widget(lbl).id)
Output 1
2
3
Example 4 — Inheritance and super()
class Vehicle:
    def __init__(self, brand):
        self.brand = brand

class Car(Vehicle):
    def __init__(self, brand, model):
        super().__init__(brand)
        self.model = model

c = Car("Honda", "Civic")
print(c.brand, c.model)
Output Honda Civic
Example 5 — Constructor Overloading via Defaults
class Box:
    def __init__(self, w=1, h=1, d=1):
        self.w, self.h, self.d = w, h, d
    def volume(self):
        return self.w * self.h * self.d

print(Box().volume())
print(Box(2, 3).volume())
print(Box(2, 3, 4).volume())
Output 1
6
24
Example 6 — __new__ (advanced)
class Singleton:
    _inst = None
    def __new__(cls):
        if cls._inst is None:
            cls._inst = super().__new__(cls)
        return cls._inst

a, b = Singleton(), Singleton()
print(a is b)
Output True

Real-World Use Cases

User Setup

Initialise user objects with username, password hash, and timestamps.

DB Connections

Establish the connection inside the constructor of a DB wrapper.

File Readers

Open the file in __init__ so the reader is ready to use.

Auth Tokens

Generate or validate token state during object creation.

Pricing Rules

Receive base price and discount; store calculated final price.

Configuration Objects

Validate settings up-front before the app runs.

Notes & Pro Tips

  • Always initialise every attribute the class will use — avoid 'maybe-set' attributes.
  • Validate inputs early; raise meaningful exceptions if invalid.
  • Call super().__init__() in subclasses to keep parent invariants.
  • Avoid heavy work in constructors — keep them quick and predictable.
  • Use @dataclass when you mostly assign attributes from arguments.
  • __new__ is rarely needed; reach for it only for singletons, immutable subclasses, or metaclasses.

Common Mistakes

  • Forgetting self: turns the constructor into an unbound function.
  • Missing super().__init__(): parent state remains uninitialised.
  • Mutable default arguments: shared between instances, surprising bugs.
  • Doing too much in __init__: hides slow operations like DB / IO; consider factories.
  • Returning a value from __init__: raises TypeError; only __new__ can return.
  • Confusing class and instance scope: assignments inside __init__ must use self..

Practice Problems

  • Problem 1: Create a class Book with a parameterised constructor taking title, author, price.
  • Problem 2: Build a Triangle class whose constructor validates that three sides form a valid triangle.
  • Problem 3: Make a class Counter that tracks how many instances have been created.
  • Problem 4: Design a Person class and a subclass Student that uses super().
  • Problem 5: Write a Rectangle class with defaults length=1, width=1 and method area().
  • Problem 6: Implement a Singleton class using __new__.

Interview Questions

  • Q1. What is a constructor and when is it called?
  • Q2. What is the difference between __init__ and __new__?
  • Q3. Can __init__ return a value?
  • Q4. What happens if a subclass doesn't call super().__init__()?
  • Q5. Does Python support constructor overloading?
  • Q6. How do you implement default arguments in a constructor?

Frequently Asked Questions

  • Q1: What is __init__?
    It is the constructor method called automatically when you create an object. It initialises the instance's attributes.
  • Q2: What is __new__?
    __new__ is responsible for allocating and returning the new instance. It runs before __init__. You rarely override it.
  • Q3: Does Python have constructor overloading?
    Not directly. Use default arguments, *args/**kwargs, or classmethod factories to achieve similar behaviour.
  • Q4: Can a constructor return a value?
    No — __init__ must return None. Only __new__ may return the object itself.
  • Q5: Why call super().__init__()?
    To run the parent class's constructor so its state is initialised. Forgetting it can cause subtle bugs.
  • Q6: What is a default constructor?
    An __init__ with no parameters (other than self) — or the implicit one Python supplies when you don't define one.

Summary

The constructor __init__ is your chance to set up a new object before any other code touches it. Use it to assign attributes, validate inputs, call super().__init__(), and otherwise place the object in a known-good state. Keep it small, predictable, and free of heavy side-effects — your future self will thank you when the codebase grows.

Continue Learning

Previous

Go to Previous Chapter

Next

Go to Next Chapter