`self` — what it is and how Python passes it
WHAT is self?
WHY does it exist? A class is a blueprint shared by many objects. One def deposit(...) body must work for alice's account and bob's account. The method needs to know which account's balance to change. self is that "which one" — it carries the data of the current object.
class Account:
def __init__(self, owner, balance):
self.owner = owner # store ON this instance
self.balance = balance
def deposit(self, amount):
self.balance += amount # change THIS instance's balance
return self.balanceHOW Python passes self (the core mechanism)
These two lines are equivalent:
So self ← alice and amount ← 50. That's the whole trick. No hidden global, no magic — just argument binding.
Why does alice.deposit "know" about alice?
Because of the descriptor protocol. A function stored in a class is a descriptor: when you access it via an instance (alice.deposit), Python returns a bound method — a small object that remembers the instance and the function:
print(alice.deposit) # <bound method Account.deposit of <Account...>>
print(alice.deposit.__self__) # the alice instance itself
print(alice.deposit.__func__) # the underlying plain function
Derivation from scratch: rebuild self with no classes
To prove self is just an argument, let's simulate methods using plain functions and dicts (an object is "data + functions that take that data").
# An "object" is just a dict of data.
def make_account(owner, balance):
return {"owner": owner, "balance": balance}
# A "method" is a plain function whose first param is the object.
def deposit(self, amount): # <-- self chosen by us, nothing special
self["balance"] += amount
return self["balance"]
alice = make_account("Alice", 100)
print(deposit(alice, 50)) # 150 -- WE pass the object manuallyWhy this step? It shows the "automatic" self in real classes is exactly this manual passing — Python just does the deposit(alice, ...) part for you via the dot.
Worked examples
Common mistakes (steel-manned)
Active recall
Recall Q: What does
obj.m(x) translate to under the hood?
Class.m(obj, x) — the instance becomes the first positional argument.
Recall Q: Is
self a keyword?
No — it's a naming convention. Any valid name works, but always use self.
Recall Q: Why must you write
self.balance and not balance?
Bare balance is a local variable. Instance attributes live on the object, accessed via self..
Recall Q: What is a bound method?
A package of function + instance; calling it auto-injects that instance as the first arg.
Recall Feynman: explain
self to a 12-year-old
Imagine a recipe (the class) pinned in a kitchen. Many cooks (objects) use the same recipe. When a cook follows step "add sugar to your bowl", self is "your bowl" — it tells the recipe which cook's bowl to use. The recipe doesn't change; only whose bowl does. When you tell a cook "make cake!", you automatically hand them their own bowl — that handing-over is Python passing self.
Flashcards
What is self in a Python method?
alice.deposit(50) is equivalent to what explicit call?
Account.deposit(alice, 50).Is self a Python keyword?
self is standard.Why does forgetting self in def greet(): raise "takes 0 positional arguments but 1 was given"?
What is a bound method's __self__?
Why use self.balance instead of balance inside a method?
balance is a local variable; self.balance accesses the instance attribute.What does returning self enable?
obj.a().b()).How does alice.deposit know about alice?
Connections
- OOP Fundamentals
- Classes and Instances
- __init__ — the constructor
- Instance vs Class Attributes
- Bound and Unbound Methods
- Descriptor Protocol
- classmethod and staticmethod (how
clsand no first-arg differ fromself)
Concept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Dekho, self koi jaadu nahi hai — ye bas object khud hai jo method ko pehle argument ke roop mein milta hai. Jab tum likhte ho alice.deposit(50), toh Python andar-andar use Account.deposit(alice, 50) bana deta hai. Matlab dot ke left wala object automatically pehle slot mein chala jaata hai. Isi liye method ke andar self ka matlab hota hai "jis object par call hua usi ka data". Isi se alice aur bob ke accounts alag-alag rehte hain, chahe deposit ka code ek hi ho.
Sabse important baat: self ek keyword nahi, sirf ek convention hai. Tum chaaho toh this ya banana bhi likh sakte ho, par sab log self use karte hain taaki code readable rahe. Aur instance ka data access karne ke liye hamesha self.balance likho — sirf balance likhoge toh Python use local variable samjhega aur NameError ya galat result aayega.
Do common galtiyan yaad rakho. Pehli: method define karte waqt self likhna bhool jaana — phir C().greet() pe error aata hai "takes 0 arguments but 1 was given", kyunki Python instance toh phir bhi bhej raha hai. Doosri: alice.deposit(alice, 50) likhna — tum self do baar de rahe ho, dot already de chuka hai. Bas alice.deposit(50) kaafi hai.
Ek line mein mantra: "Dot fills the slot." Jis object ke aage dot lagaya, wahi self ban gaya. Yahi pure OOP ka foundation hai — ek hi blueprint, alag-alag objects, har ek apna data self ke through sambhaale hue.