self keyword

Understanding self in Python with Examples

When we create several objects from a class, each object can hold different data. A method needs a way to access the data of the object on which it is called.

In an instance method, self refers to the object receiving the method call.

Although people sometimes call it the “self keyword,” self is not a Python keyword. It is the standard name used for the first parameter of an instance method.

Let us understand it through a few examples.

Accessing the Current Object

Consider this simple class:

class Student:
    def display(self):
        print("Name:", self.name)


student1 = Student()
student1.name = "Rahul"

student1.display()

Output:

Name: Rahul

When we call:

student1.display()

Python automatically passes the object referenced by student1 to the method’s first parameter, self.

Inside this call:

self.name

accesses the same attribute as:

student1.name

We write self.name inside the method so that the method can work with any Student object.

Using the Same Method with Different Objects

Let us create two students:

class Student:
    def display(self):
        print("Name:", self.name)


student1 = Student()
student1.name = "Rahul"

student2 = Student()
student2.name = "Anjali"

student1.display()
student2.display()

Output:

Name: Rahul
Name: Anjali

The method is defined only once, but it displays different names.

Method call self refers to self.name
student1.display() The first student object "Rahul"
student2.display() The second student object "Anjali"

self does not permanently refer to one particular object. Its value depends on the object used in that call.

Seeing How the Object Is Passed

For the method above, these two calls are equivalent:

student1.display()
Student.display(student1)

Output:

Name: Rahul
Name: Rahul

In the first call, Python supplies the object automatically. In the second, we explicitly supply it through the class.

This explains why the definition contains a parameter even though the usual call has no arguments inside the parentheses:

def display(self):
    print("Name:", self.name)
student1.display()

The object before the dot supplies self.

Using self inside __init__()

We can initialize student details when creating the object:

class Student:
    def __init__(self, name, marks):
        self.name = name
        self.marks = marks


student1 = Student("Rahul", 85)
student2 = Student("Anjali", 92)

print(student1.name, student1.marks)
print(student2.name, student2.marks)

Output:

Rahul 85
Anjali 92

During initialization, self refers to the newly created instance.

Look closely at this assignment:

self.name = name
Expression Meaning
name A local parameter receiving the supplied name
self.name An attribute belonging to the object

For the first student, the assignment stores "Rahul" in that object’s name attribute.

The parameter and attribute do not need matching names. This also works:

class Student:
    def __init__(self, student_name, student_marks):
        self.name = student_name
        self.marks = student_marks

Using matching names is simply a common, readable convention.

Updating the Object’s Data

A method can use self to change the object’s attributes.

class Student:
    def __init__(self, name, marks):
        self.name = name
        self.marks = marks

    def add_marks(self, extra_marks):
        self.marks += extra_marks


student1 = Student("Rahul", 80)
student2 = Student("Anjali", 90)

student1.add_marks(5)

print(student1.name, student1.marks)
print(student2.name, student2.marks)

Output:

Rahul 85
Anjali 90

In this call:

student1.add_marks(5)

the parameters receive:

Parameter Value
self The object referenced by student1
extra_marks 5

Only Rahul’s marks change because self.marks accesses the first student’s attribute during this call.

Calling Another Method through self

An instance method can call another method on the same object.

class Student:
    def __init__(self, name, marks):
        self.name = name
        self.marks = marks

    def get_result(self):
        if self.marks >= 40:
            return "Pass"
        return "Fail"

    def display(self):
        print("Name:", self.name)
        print("Marks:", self.marks)
        print("Result:", self.get_result())


student1 = Student("Rahul", 85)
student2 = Student("Anjali", 35)

student1.display()
print()
student2.display()

Output:

Name: Rahul
Marks: 85
Result: Pass

Name: Anjali
Marks: 35
Result: Fail

Inside display():

self.get_result()

calls get_result() on the same student object.

When student1.display() runs, it calculates Rahul’s result. When student2.display() runs, it calculates Anjali’s result.

Forgetting self in the Method Definition

Consider this incorrect definition:

class Student:
    def display():
        print("Student details")


student1 = Student()
student1.display()

Error:

TypeError: Student.display() takes 0 positional arguments but 1 was given

Although we wrote no arguments inside the parentheses, Python automatically passed the student object. The method definition has no parameter to receive it.

Correct the definition by adding self:

class Student:
    def display(self):
        print("Student details")

An ordinary instance method needs this first parameter even if its body does not use the object.

Creating a Local Variable Instead of Updating an Attribute

Here is another mistake:

class Student:
    def __init__(self, marks):
        self.marks = marks

    def update_marks(self, new_marks):
        marks = new_marks


student1 = Student(70)
student1.update_marks(95)

print(student1.marks)

Output:

70

The statement:

marks = new_marks

creates a local variable. It does not change the object’s attribute.

Use:

def update_marks(self, new_marks):
    self.marks = new_marks

Now calling student1.update_marks(95) changes the object’s marks to 95.

Can We Use a Different Name?

Because self is not a keyword, another parameter name is technically allowed:

class Student:
    def __init__(current, name):
        current.name = name

    def display(current):
        print(current.name)


student1 = Student("Rahul")
student1.display()

Output:

Rahul

Python passes the instance to the first parameter, regardless of that parameter’s name.

However, use self in your programs. It is the convention Python programmers expect.

Practice: A Counter Object

Create a Counter class with:

  • An instance attribute named count, initialized to 0.

  • An increment() method that increases self.count by 1.

  • A display() method that prints self.count.

Test it with:

counter1 = Counter()
counter2 = Counter()

counter1.increment()
counter1.increment()

counter2.increment()

counter1.display()
counter2.display()

Expected output:

2
1

As you trace each call, ask: “Which object does self refer to right now?” That tells you exactly which object’s count will be read or updated.

Previous Topic Types of Variables