Self in Python class
Tags: tutorial, python, beginners, oop
Published: 2020-09-14 07:58:47

Hey everyone in this tutorial I want to share what I learned about `self` in python, As far as I know, this is one of the things that most of the beginners like me have a problem understanding in _OOP_ and _Classes_!
I'm here to write like a beginner(Simple) not a Pro(difficult) to give you a light and show you how cool it is when you understand what does exactly `self` do behind the scene, so No more _pain_ when you want to create a class!
so let's dive into it and improve our coding skills:

First, you need to know about two things:

>1. __Method__: _A function which is associated with a class_

>2. __Attributes__: _Some data that is related to a class_

So, we want to have a Class(Object) for our College or University and want to represent students with python codes!
In this cause we can have class cause every student can have some methods and attributed like age, name, email, loan, pay and etc.


*****

>__💡 Note: Make sure you are starting your class name with an upper case letter. (It's a convention!) like:
`class Name:
   pass`__

Let's create our first class >>> :
```python 
class Student:
    pass


```
* What is the Differences between class and instance of a class?


>A class is like a blueprint and a sample for creating instances, and every student that we'll create would be an instance of our Student() class and every instance is unique! (It means they are in different locations in memory). 
Take a look at this example below:
```python
class Student:
    pass


first_student = Student()
second_student = Student()

```
In this case `first_student` and `second_student` are the instances of our `Student()` class.

*What did I mean when I said every instance is unique?
> Let's print our two instances and see what will happen...
```python
print(first_student, second_student)
```
__Output__:
```
>>> <__main__.Student object at 0x7f68e60b0820>
 
<__main__.Student object at 0x7f68e60b0d30>
```
as you can see they are in different locations in Memory(b0820 and b0d30).
***

I want to show you how hard it is if you code instance variable manually without using class!
```python
class Student:
    pass


first_student = Student()
second_student = Student()


first_student.first_name = "James"
first_student.last_name = "White"
first_student.email = "James.White@collegename.com"
first_student.age = 21
first_student.loan = 1000

second_student.first_name = "Leo"
second_student.second_name = "Ledger"
second_student.email = "Leo.Ledger@collegename.com"
second_student.age = 45
second_student.loan = 2400 
```
So here we have 5 attributes that are unique to the instances.
let's look at this example:
```python
print(first_student.age, second_student.age)
```
__Output:__
```
>>> 21 45
```
But as you saw we wrote 10 lines of code for only 5 attributes, there's another way to do it.
If we want to do all of these tasks automatically and save your time we have to use a special method which is called `def __init__` method!(which means __initialize__).

>__💡 Note: It's a convention to use self when you want to call instances in Classes.__
_After self you can define your arguments ._

Inside of our `def __init__` method 
```python
class Student:
    def __init__(self, first_name, last_name, age, loan):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age
        self.loan = loan
        self.email = first_name + last_name + "@collegename.com"
```
***
> What does "self" do in python class?
If we compare the above examples, we created instance variables in two ways:
1. Manually
2. Automatically
let's take a look at the `first_name` variable when we created Manually:

```python
first_student.first_name = "James"
```
and Automatically:
```python
class Student:
    def __init__(self, first_name):
        self.first_name = first_name

```
and Comparing both of them...
```python 
Manually: 

first_student.first_name = "James"


VS 

Automatically:


def __init__(self, first_name):
        self.first_name = first_name
```
As you can see, the self exactly behave like an instance which means 
`self` is equal to `first_student`.
So when we call `self` in our Classes it behaves like instances but in an automatic way!
So when we pass `self` in our `def __init__` method it will replace self with instances that you define.
Take a look at this example to understand what do I mean:
```python
class Student:
    def __init__(self, first_name, last_name, age, loan):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age
        self.loan = loan
        self.email = first_name + last_name + "@collegename.com"


first_student = Student("Muhammad", "Khanjani", 22, 2000)

print(first_student.first_name)
```
when we write:

```python
first_student = Student("Muhammad", "Khanjani", 22, 2000)
print(first_student.name)

```
__Output:__
```
Muhammad
```
The `__init__` method will be run automatically, so the first student will be passed as `self` in our class and will set all of the attributes that we defined in `Student("Muhammad", "Khanjani", 22, 2000)`!
so, for the other:
```python
Manually:
self.last_name = last_name
self.age = age
self.loan = loan
self.email = first_name + last_name + "@collegename.com"

VS


Automatically:

first_student.last_name = "White"
first_student.email = "James.White@collegename.com"
first_student.age = 21
first_student.loan = 1000

```
So you can think `self` exactly as an instance in python class!

__Complete Comparison between Manually and Automatically(using `self` and `init` method!)__:
```python
class Employee:
    def __init__(self, first, last, pay):
        self.firstname = first
        self.lastname = last
        self.pay = pay
        self.email = first + "." + last + "@banji.com"  
    def fullname(self):
        return f"{self.firstname} {self.lastname}"
emp_1 = Employee("MuhammadHussein", "Khanjani", 5000)
emp_2 = Employee("Farshid", "Keshavaz", 2000)
print(emp_1.firstname)
print(emp_2.email)




VS 




class Employee2:
    pass
emp_1 = Employee2()
emp_2 = Employee2()
emp_1.firstname = 'Walter'
emp_1.lastname = 'White'
emp_1.full_name = emp_1.firstname + emp_1.lastname
emp_1.email = 'Walter.White@gmail.com'
emp_1.pay = 50000
emp_2.firstname = 'Jesse'
emp_2.lastname = 'Pinkman'
emp_2.full_name = emp_2.firstname + emp_2.lastname
emp_2.email = 'Jesse.Pinkman@gmail.com'
emp_2.pay = 2000
print(emp_1.firstname)
print(emp_2.email)
```

This is the first part of `self` in python and classes, I don't want to write too long, cause it will be tedious for beginners like me!
_I hope you get the purposes of the `self` in classes, but if you need more explanation and you think you can write more clear and adding something to this post just let me know and leave a comment below, share your knowledge and point of view with us._

Thank you for reading my post.


#Keep Moving Forward __ツ__

##Enjoy Your Journey 👊

###Code with __💛__

__🅑🅐🅝🅙🅘__