__init__ and self
The constructor method that runs automatically when an object is created, and self — the reference every method uses to access its own object.
"__init__ runs automatically the moment you create an object. It is your one chance to set up the object with everything it needs from birth."
— ShurAIWhat is __init__?
__init__ (pronounced "dunder init") is the constructor method. Python calls it automatically every time you create a new object from a class. You use it to set the starting values for the object's attributes:
class Person:
def __init__(self, name, age):
self.name = name # store name on this object
self.age = age # store age on this object
# Python automatically calls __init__(p, "Riya", 22)
p = Person("Riya", 22)
print(p.name) # Riya
print(p.age) # 22
What is self?
self is a reference to the current object. It is how a method knows which specific object it is working with. When you call p.greet(), Python passes p in as self automatically:
greet(self), self is the same object as p. self.name reads p.name.class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f"Hi, I'm {self.name} and I'm {self.age} years old.")
p1 = Person("Riya", 22)
p2 = Person("Arjun", 25)
p1.greet() # Hi, I'm Riya and I'm 22 years old.
p2.greet() # Hi, I'm Arjun and I'm 25 years old.
# self.name differs because self is a different object each time
Default Parameter Values in __init__
class Player:
def __init__(self, name, level=1, score=0):
self.name = name
self.level = level
self.score = score
def status(self):
print(f"{self.name} — Level {self.level} — Score {self.score}")
# Only name required; level and score use defaults
p1 = Player("Riya")
p2 = Player("Arjun", level=5, score=1200)
p1.status() # Riya — Level 1 — Score 0
p2.status() # Arjun — Level 5 — Score 1200
Python doesn’t enforce the name self — you could call it anything. But every Python programmer in the world uses self. Always use self. Breaking this convention makes your code unreadable.
Real Example — Shopping Cart Item
class CartItem:
def __init__(self, name, price, qty=1):
self.name = name
self.price = price
self.qty = qty
def total(self):
return self.price * self.qty
def summary(self):
print(f"{self.name} x{self.qty} @ ₹{self.price} = ₹{self.total()}")
items = [
CartItem("Rice", 80, 2),
CartItem("Oil", 150, 1),
CartItem("Biscuit", 30, 4),
]
for item in items:
item.summary()
print(f"Total: ₹{sum(i.total() for i in items)}")
Rice x2 @ ₹80 = ₹160
Oil x1 @ ₹150 = ₹150
Biscuit x4 @ ₹30 = ₹120
Total: ₹430
"Think of __init__ as the birth certificate of every object. It is where you record all the vital information the object will carry with it for its entire lifetime."
— ShurAI🧠 Quiz — Q1
When does __init__ run?
🧠 Quiz — Q2
What is self in a method?
🧠 Quiz — Q3
You write self.score = 0 inside __init__. What does this do?
🧠 Quiz — Q4
Why does every method in a class have self as its first parameter?