Python Essentials for AI Engineer

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

Python
class Counter:    def __init__(self):        self.n = 0    def bump(self):        self.n += 1        return self.nc = Counter()print(c.bump())              # 1print(Counter.bump(c))       # 2  -> exactly what c.bump() doesprint(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

Python
class Broken:    def greet():                      # forgot 'self' in the parameters        return "hi"try:    Broken().greet()except TypeError as e:    print(e)      # Broken.greet() takes 0 positional arguments but 1 was givenclass Forgetful:    def __init__(self):        self.items = []    def add(self, x):        items = [x]                   # forgot 'self.': creates a local, discards itf = Forgetful(); f.add("a")print(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) take cls: 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:

Python
class ChatSession:    def __init__(self, user_id):        self.user_id = user_id        self.history = []                      # this session's own list    def add(self, role, content):        self.history.append({"role": role, "content": content})        return len(self.history)asha, ravi = ChatSession("asha"), ChatSession("ravi")asha.add("user", "My refund for order 1142?")asha.add("assistant", "It was issued on Monday.")ravi.add("user", "How do I change my UPI PIN?")print(len(asha.history), len(ravi.history))    # 2 1

self.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 self a 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.