The __init__ Constructor
Learn how __init__ automatically sets up a new object the moment it is created, and why that makes your classes so much more powerful.
Imagine ordering a coffee. The moment you place the order, the barista already knows: what size, what flavour, your name for the cup. You did not have to hand those details over one by one after the cup appeared — they came built-in from the start.
That is exactly what __init__ does for Python objects. It is a special method that runs automatically the instant you create a new instance of a class. By the time you have a shiny new object in your hands, all its starting details are already set.
See it in action
— step through the idea, then dive into the details below.Objects That Arrive Ready
Every time you create an object, Python can automatically run setup code for you. That magic happens inside a special method called __init__.
#Classes vs Instances — a quick reminder
Blueprint vs Building
A class is like an architect's blueprint. It describes what every building of that type will look like. An instance is one actual building constructed from that blueprint. You can build many buildings from one blueprint, and each building can have its own address, colour, and number of floors.
class Dog:
pass
rex = Dog() # rex is one instance
bella = Dog() # bella is a different instance
print(rex) # different objects in memory
print(bella)Right now Dog is empty. Every dog is identical and anonymous. Let's fix that with __init__.
#Writing Your First __init__
class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed
rex = Dog("Rex", "Labrador")
print(rex.name)
print(rex.breed)Let's break down what happened line by line:
def __init__(self, name, breed):— defines the setup method. It always receivesselfas its first argument.self.name = name— stores the value ofnameon the object itself. Think of it as pinning a name tag to that specific dog.Dog("Rex", "Labrador")— Python creates a newDogand immediately calls__init__with"Rex"and"Labrador". You never see that call — Python makes it for you.
#What is 'self'?
Self = 'this very object'
self is just a name (you could technically use any word, but never do — always use self). It refers to the specific instance being set up right now. When Python runs rex = Dog("Rex", "Labrador"), it passes rex as self automatically. So self.name = name really means rex.name = "Rex".
#Each Instance Has Its Own Attributes
class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed
rex = Dog("Rex", "Labrador")
bella = Dog("Bella", "Poodle")
print(rex.name, rex.breed)
print(bella.name, bella.breed)#Default Parameter Values
Sometimes you want a sensible default so callers do not have to provide every value. You can give __init__ parameters default values just like any other Python function.
class Dog:
def __init__(self, name, breed="Unknown"):
self.name = name
self.breed = breed
dog1 = Dog("Max", "Beagle") # breed provided
dog2 = Dog("Buddy") # breed uses default
print(dog1.name, dog1.breed)
print(dog2.name, dog2.breed)Put defaults at the end
Parameters with defaults must always come after parameters without defaults. def __init__(self, name, breed="Unknown") is fine. def __init__(self, breed="Unknown", name) would raise a SyntaxError.
#You Never Call __init__ Directly
Don't call __init__ yourself
You should never write rex.__init__("Rex", "Labrador") in normal code. Python calls it for you when you write Dog("Rex", "Labrador"). Calling it manually would run the setup code a second time on an already-created object, which is almost always a bug.
#A Richer Example
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
print(f"{self.owner} deposited ${amount}. Balance: ${self.balance}")
account = BankAccount("Alice", 100)
account.deposit(50)Notice that deposit can read self.owner and self.balance because __init__ stored them on the object. Every method in the class can access attributes set in __init__ through self.
#Computed Attributes
Not every attribute has to come directly from a parameter. You can compute values inside __init__ too.
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
self.area = width * height # computed at creation time
r = Rectangle(5, 3)
print(r.area)What does Python do when you write `dog = Dog("Rex", "Labrador")`?
Key takeaways
- `__init__` runs automatically every time you create a new instance — you never call it yourself.
- Use `self.attribute = value` inside `__init__` to store data on the specific object being created.
- Arguments you pass at `Dog("Rex")` flow directly into `__init__`'s parameters (after `self`).
- Default parameter values let callers skip optional arguments: `def __init__(self, name, breed="Unknown")`.
- A class is the blueprint; an instance is a real object built from it — each instance has its own independent attributes.
What does this code print?
class Dog:
def __init__(self, name, breed="Unknown"):
self.name = name
self.breed = breed
dog1 = Dog("Rex", "Labrador")
dog2 = Dog("Buddy")
print(dog1.name, dog1.breed)
print(dog2.name, dog2.breed)This code has a bug. What is wrong?
class Rectangle:
def __init__(self, width, height):
width = width
height = height
self.area = width * height
r = Rectangle(4, 5)
print(r.area)
print(r.width)Complete the __init__ method so that a BankAccount stores the owner's name and a starting balance, then prints correctly.
class BankAccount: def __init__(self, owner, balance=0): self.owner = self.balance = acc = BankAccount("Alice", 100) print(acc.owner) print(acc.balance)
Put these lines in the right order to define a Movie class and print the title of a new instance.
m = Movie("Inception", 2010)self.title = title
print(m.title)
class Movie:
self.year = year
def __init__(self, title, year):
Create a class called Movie with an __init__ method that accepts title, director, and year. Give year a default value of 2024. Then create two Movie instances: one with all three arguments, and one using only title and director. Print the title and year of each.
Try it live — edit the code and hit Run to execute real Python: