A constructor is a special method that runs automatically when you create a new object from a class. In Python, the constructor is always named __init__. Its job is to initialise the object's attributes — setting up the starting state of each new instance so it is ready to use immediately.

Why do objects need a constructor?

When you create a class, you are writing a template. The class itself holds no data — it merely describes the structure. Every time you create an instance (a concrete object from that template), the constructor runs and sets up that specific object's attributes with their initial values.

Think of a class as a blank enrolment form and a constructor as the process of filling it in with a specific student's details. The form (class) defines the fields; the filled-in version (object) holds the actual data.

Without a constructor, you would have to manually set every attribute on the object after creating it, which is error-prone and inconsistent.

What does a Python constructor look like?

class Student:
    def __init__(self, name, age, year_group):
        self.name = name
        self.age = age
        self.year_group = year_group

# Creating two Student objects
student1 = Student("Alice", 14, 9)
student2 = Student("Bob", 15, 10)

print(student1.name)       # Output: Alice
print(student2.year_group) # Output: 10

Key points to notice:

  • __init__ is the constructor. The double underscores make it a dunder method (short for "double underscore"), also called a magic method.
  • self is always the first parameter. It refers to the specific instance being created — it is how Python knows which object's attributes to set. You never pass self explicitly when calling the constructor; Python inserts it automatically.
  • self.name = name creates an instance attribute called name on this specific object and assigns it the value passed in.

How does self work?

self is the current object — the one being constructed or used. Every instance method in Python receives self as its first parameter. When you write self.name, you are saying "the name attribute of this particular object".

class Counter:
    def __init__(self, start):
        self.count = start    # instance attribute

    def increment(self):
        self.count += 1       # updates this object's count

c1 = Counter(0)
c2 = Counter(100)

c1.increment()
print(c1.count)    # Output: 1
print(c2.count)    # Output: 100  — c2 is unaffected

Each object has its own separate copy of count. Changing c1.count does not affect c2.count — that is the whole point of objects.

Can a constructor have default parameter values?

Yes. You can give constructor parameters default values, making them optional when creating objects.

class Product:
    def __init__(self, name, price, in_stock=True):
        self.name = name
        self.price = price
        self.in_stock = in_stock   # defaults to True if not supplied

p1 = Product("Notebook", 1.99)           # in_stock defaults to True
p2 = Product("Pen", 0.50, False)         # in_stock explicitly False

print(p1.in_stock)   # Output: True
print(p2.in_stock)   # Output: False

Default parameters must come after non-default parameters in the method signature — otherwise Python cannot work out which argument corresponds to which parameter.

What is the difference between class attributes and instance attributes?

Attribute type Defined Shared? Example
Instance attribute Inside __init__ using self.x = ... No — unique to each object self.name = name
Class attribute Inside the class body, outside any method Yes — shared by all instances species = "Human"
class Animal:
    kingdom = "Animalia"     # class attribute — shared

    def __init__(self, name, sound):
        self.name = name     # instance attribute — unique
        self.sound = sound

cat = Animal("Cat", "Meow")
dog = Animal("Dog", "Woof")

print(cat.kingdom)    # Output: Animalia
print(dog.kingdom)    # Output: Animalia  (same class attribute)
print(cat.name)       # Output: Cat
print(dog.name)       # Output: Dog  (each has its own)

What happens if a class has no constructor?

If you define a class without __init__, Python provides a default constructor that creates the object with no attributes. You can still create instances, but they will have no initial attributes unless you assign them manually after creation. This is valid but unusual and not recommended — constructors make your code more predictable and safer.

class Empty:
    pass

e = Empty()         # Works fine — but no attributes set
e.x = 10            # Manually adding an attribute afterwards
print(e.x)          # Output: 10

Frequently asked questions

Do I always need to include self as the first parameter?

Yes, self must always be the first parameter of any instance method, including __init__. If you omit it, Python will raise a TypeError when you call the method, because it tries to pass the instance automatically but there is no parameter to receive it. The name self is a convention — technically you could use any name — but using anything other than self is strongly discouraged and would cost marks in an exam if it caused confusion.

Can a constructor call other methods?

Yes. Inside __init__, you can call other methods of the same class using self.method_name(). This is useful for validation or complex initialisation logic. For example, a constructor might call a method to check that a supplied age is positive before assigning it, rather than placing all the validation logic inside __init__ itself. Keeping __init__ focused on setting attributes and delegating logic to named methods improves code readability.

How is a constructor different from a regular method?

A constructor (__init__) runs automatically whenever a new object is created using the class name. A regular method must be called explicitly using the object and dot notation (e.g. student1.get_grade()). Constructors also cannot return a value (other than None) — if you try to return a non-None value from __init__, Python raises a TypeError.

What is a destructor in Python?

Python has a corresponding __del__ method called the destructor, which runs when an object is about to be removed from memory (garbage collected). At GCSE level, you are not expected to write destructors. Python's memory management handles cleanup automatically, so destructors are rarely needed in practice and are largely an advanced topic.


Build your own OOP classes step by step, with instant hints from Professor Turing, at aitutors.me.