Self in Python
“self" is neither a keyword nor has a special meaning in Python, but it has a place and a job to do in Object-oriented programming. When we create a class and write a function in it, we use self as the function's first parameter. This article will discuss about the "self in Python” with examples.
What is self in Python?
A class is like a blueprint for its instances/ objects. We can create multiple objects for a class, and every object can have its attributes. The class must be able to store all the different sets of attributes of individual objects created, and for which self is used.
Let us take an example:
class addition:
def __init__ (self, a, b):
self. a = a;
self. b = b;
def add (self):
sum = self. a + self. b;
print ("The addition of a =",self. a, "and b =", self. b, "is", sum)
obj = addition (4, 5)
obj. add ()
obj1 = addition (3, 4)
obj. add ()
obj1. add ()
Output:
The addition of a = 4 and b = 5 is 9
The addition of a = 3 and b = 4 is 7
Understanding:
In the above program, we created a class named addition, in which we used 2 methods – init and add. In the first method, we used self as the first parameter and the second parameter as the only parameter.
In the init method, we used the self variable to initialize the parameters, a and b. We tell the class that every object created can have its values for a and b. So, variables a and b can hold different values for different objects, and the class can keep track of the values.
As you can observe, we created two objects, obj, and obj1. We gave different arguments to both the objects and called the add method from the class. In the add method, we gave self as the only parameter. Using it, we accessed the values of a and b variables.
- There are class methods, instance methods, and static methods in Python, and self is necessary to be used in Instance methods.
- When we pass external arguments to class methods, they become instance methods. These methods are used to get details about specified objects/ instances of the class.
- The above example is an instance method.
Let us take another example:
class car:
def __init__ (self, model, number, state):
self. model = model
self. number = number
self. state = state
def info_display (self):
print ("Model of the car:", self. model)
print ("Number of the car:", self. number)
print ("The car is purchased in:", self. state)
obj = car("Hyundai Elantra Hybrid", "3409", "Tamil Nadu")
obj. info_display ()
Output:
Model of the car: Hyundai Elantra Hybrid
Number of the car: 3409
The car is purchased in Tamil Nadu
Understanding:
We created a class car in which we created two instance methods - __init__ and info_display. After creating an object-obj, we passed arguments to the parameters- model, number, and state. These arguments are assigned to obj in the init method, and when we call the info_disply method, the information about the car is printed.
Look at the program like this:
- ***When an object is created to a class, the object replaces self, or in other words, it is passed as an argument to the self parameter***
- Look at the above program and replace self with obj to understand the mechanism.
def __init__ (obj, model, number, state):
obj. model = model
obj. number = number
obj. state = state
Now, you can understand that the arguments passed are all assigned as the instance arguments in the __init__ method.
- This way, every object can have its attributes and methods.
- When we access the instance attributes using the self:
def info_display (obj):
print ("Model of the car:", obj. model)
print ("number of the car: ", obj. number)
print ("The car is purchased in: ", obj. state)
In the init method, these attributes are assigned, and hence, we can access them now in the method using the self parameter.
Internal Mechanism:
class add_sub:
def __init__(self, a, b):
self. a = a
self. b = b
def add (self):
c = self. a + self. b
print("The sum of", self. a, "and", self. b, "is", c)
def sub (self):
d = self. a - self. b
print("The difference between", self. a, "and", self. b, "is", d)
obj1 = add_sub (2, 3)
obj1. add ()
obj2 = add_sub (8, 2)
obj2. sub ()
Let us take a simple example first:
Output:
of 2 and 3 is 5
The difference between 8 and 2 is 6
- We wrote 2 methods – add and sub in the class add_sub. As you can observe, including self, there are 3 parameters in both the methods. When we called them, we didn’t give 3 arguments and gave only 2 arguments. But, it didn’t raise any error. How did it process? Let us see:
- When we write a function in a class and call it with an object, it is no longer a function. It becomes a method.
In the above program:
add_sub. add () is the function and obj1. add () is a method. You can observe it here:
print (type (add_sub.add))
print (type (obj1.add))
Output:
<class 'function'>
<class 'method'>
- Internally, when a method is called, the object that is calling the method is automatically passed as an argument to the corresponding function. So, when we call a method like:
- obj1. add ()
- By default, it becomes:
add_sub. add (obj1)
- In a single sentence,
*When a method is called with or without any arguments, the class function with the object as the first argument is automatically called. *
Obj. method (arguments) -> Class. function (Obj, arguments)
- Hence, calling a method is automatic but receiving is not. Hence, we need to leave the space for the object to fit in for which we use self.
- Programmers got habituated to writing self, but that word does not hold any special meaning in Python.
- Self is necessary because, unlike other programming languages, Python does not support the "@" syntax to access the attributes of an object.
Static methods:
When creating static methods in Python, this parameter can be avoided. If you are unaware of this concept, static methods are also methods like class methods, but unlike them, they don't need an object. We can call or use these methods without the need for an object.
We can create a static method in many ways. One of those ways is to use the decorator: @staticmethod.
This decorator makes a method as static.
The concept here is that we can avoid passing self as the first parameter in static methods:
class class1 (object):
@staticmethod
def method ():
print ("No self is passed")
a = class1 ()
a.method ()
class1. method ()
Output:
No self is passed
No self is passed
We used the decorator @staticmethod to declare method () as a static method. You can observe that we did not pass any arguments, not even self, to the method. We created an object and called the method, and we called the method using the class name. We got the output in both the calls.
print (type (class1. method ))
print (type (a. method ))
Output:
<class 'function'>
<class 'function'>
You can observe that both the calls are functions and not methods. Hence, a static method behaves like a normal function, so they don't need a self parameter.
- Self is not a Python discovery. It is derived from a programming language named “Modula-3”.
- Programmers suggested making self a keyword like "this" in other languages, but it is not accepted yet.
- We can use other names in the place of self, but self is suggested because it improves the readability of the code.
Example using other word in place of self
class add_sub:
def __init__ (word, a, b):
word .a = a
word. b = b
def add (word):
c = word. a + word. b
print ("The sum of", word. a,"and", word. b, "is", c)
obj1 = add_sub (2, 3)
obj1. add ()
Output:
The sum of 2 and 3 is 5
You can observe that in the place of self, we used “word”.
- The creator of Python, "Guido van Russom” created a blog addressing several details about self. You can read it here.
- What if we don’t specify self?
Let us see:
class car:
def info_display ():
print ("No self")
obj = car ()
obj. info_display ()
Output:
Traceback (most recent call last):
File "D:\Programs\python\untitled0.py", line 12, in <module>
obj. info_display ()
TypeError: info_display() takes 0 positional arguments but 1 was given
This error is raised because the method info_display () does not take any arguments. Still, when we create an object and call the method using the object, the object is automatically passed as an argument to the method for which there is no slot like self.