Understanding OOP self
The problem...
You've seen self in every method. You've written it without fully understanding it. It's always the first parameter. Python seems to handle it automatically. But what is it, exactly — and why does it exist?
The idea!
When you call a method on an object, Python needs to know which object you're talking about.
You might have ten Animal objects. When you call lassie.describe(), Python needs to know that self.name refers to Lassie's name — not Whiskers', not Rex's. self is how Python keeps track of which object is being used.
What self actually is
When you write:
lassie.describe()
Python translates this internally to:
Animal.describe(lassie)
The object lassie is passed as the first argument — and that argument is received as self inside the method.
So self is not a keyword. It's not magic. It's just the name — by convention — for the first parameter that receives the object. You could name it anything. But everyone names it self, and so should you.
Why self is needed
Without self, a method inside a class has no way to know whose data it's working with:
class Animal:
def __init__(self, name):
self.name = name
def describe(self):
print(f"My name is {self.name}.") # self.name — this object's name
lassie = Animal("Lassie")
whiskers = Animal("Whiskers")
lassie.describe() # My name is Lassie.
whiskers.describe() # My name is Whiskers.
Same method. Two different objects. self is what makes them different inside the method.
self in __init__
self works exactly the same in __init__. When you write self.name = name, you're storing the value on the specific object being created — not on the class, not globally.
class Animal:
def __init__(self, name):
self.name = name # stored on this specific object
lassie = Animal("Lassie")
whiskers = Animal("Whiskers")
print(lassie.name) # Lassie
print(whiskers.name) # Whiskers
Two calls to __init__. Two different self values — one for lassie, one for whiskers. Each stores its own name independently.
self is passed automatically
You never pass self manually. Python does it for you every time you call a method on an object.
lassie.describe() # you pass nothing
# Python passes lassie as self automatically
If you try to pass it manually, you'll get an error — too many arguments.
Calling one method from another
Inside a class, methods call each other through self:
class Animal:
def __init__(self, name, health):
self.name = name
self.health = health
self.status = "available"
def is_healthy(self):
return self.health == "healthy"
def describe(self):
health_note = "healthy" if self.is_healthy() else "needs care"
print(f"{self.name} is {health_note} and {self.status}.")
lassie = Animal("Lassie", "ill")
lassie.describe() # Lassie is needs care and available.
self.is_healthy() inside describe() — one method calling another on the same object. self is the thread that connects them.
Heads up!
selfis not a keyword — it's a convention. Everyone uses it. You should too.- Python passes
selfautomatically — never pass it manually self.attraccesses the object's own data — not the class, not a global variable- Every method in a class must have
selfas its first parameter
The mindset shift
Stop thinking: "self is just a formality I have to write."
Start thinking: "self is how the object refers to itself — the thread that connects all its data and methods."
What you should understand now
selfis the object that a method is called on- Python passes it automatically — you never do it manually
self.attraccesses that specific object's data- Without
self, a method has no way to know which object it's working with - Methods call each other through
self.method()