Course Content
Python Essentials for AI Engineer
6 sections · 48 lessons
What is self in Python?
What you need to know
What Python does behind the scenes
1class Counter:2 def __init__(self):3 self.n = 045 def bump(self):6 self.n += 17 return self.n89c = Counter()10print(c.bump()) # 111print(Counter.bump(c)) # 2 -> exactly what c.bump() does12print(c.bump) # <bound method Counter.bump of <__main__.Counter object at 0x...>>When you access c.bump, Python creates a bound method: the function with c already attached as its first argument. Calling it supplies the remaining arguments.
Why it is explicit
Some languages have a hidden this. Python chose to make it visible in the parameter list, in line with "explicit is better than implicit". Inside a method you always see whether a name is a local variable (total) or an attribute of the object (self.total).
Two classic errors
1class Broken:2 def greet(): # forgot 'self' in the parameters3 return "hi"4try:5 Broken().greet()6except TypeError as e:7 print(e) # Broken.greet() takes 0 positional arguments but 1 was given89class Forgetful:10 def __init__(self):11 self.items = []12 def add(self, x):13 items = [x] # forgot 'self.': creates a local, discards it14f = Forgetful(); f.add("a")15print(f.items) # []The first message looks strange ("I passed nothing!") until you remember Python passes the instance automatically.
self, cls and neither
- Instance methods take
self: they need the object's data. - Class methods (
@classmethod) takecls: they need the class, for example to build a new instance. - Static methods (
@staticmethod) take neither: plain functions that live in the class for organisation.
A real-life example
A chat service keeps one ChatSession per user, so each conversation's history stays separate:
1class ChatSession:2 def __init__(self, user_id):3 self.user_id = user_id4 self.history = [] # this session's own list56 def add(self, role, content):7 self.history.append({"role": role, "content": content})8 return len(self.history)910asha, ravi = ChatSession("asha"), ChatSession("ravi")11asha.add("user", "My refund for order 1142?")12asha.add("assistant", "It was issued on Monday.")13ravi.add("user", "How do I change my UPI PIN?")14print(len(asha.history), len(ravi.history)) # 2 1self.history resolves to a different list for asha and ravi, because self is a different object in each call. If history were created without self. — or as a class attribute — the two users would share one conversation, and Ravi's prompt could contain Asha's order number.
Follow-up questions to expect
- "Is
selfa keyword?" — No. Any name works, but using anything else confuses every reader and many tools. - "What is a bound method?" — A function attached to an instance, so the instance is supplied as the first argument automatically.
- "What is
cls?" — The conventional first parameter of a@classmethod; it refers to the class, not an instance.