Loop Control Statements in C Introduction to HTML How to use the Github API The image tag, anchor tag and the button tag Ordered and Unordered Lists in HTML The division tag HTML Forms Tables in HTML Introduction to C Programming Introduction to Python Varibles and Datatypes in Python Operators in Python Typecasting in Python Input and Output in Python If Else in Python Loops in Python Break, Continue and Pass in Python Python practice section 1 Lists in Python Tuple in Python

Class and Objects in Python

There are so many data types in Python such as a list, dic etc. to store different types of data. Then why do we need classes? Suppose that you want to store details of a person like name, age, phone number etc. then what data type will you use? You can use a list but it will be difficult to manage and become messy. What if you could create a custom data type? Classes in Python do exactly that.

Creating your first python class

The syntax to create a Python Class is as follows:
class ClassName:

    def __init__(self,params):
        # define properties of object here
        self.PropertyName1=param1
        self.PropertyName2=param2

    # other methods
For example -

class Person:

    def __init__(self,name,age,phone_number) -> None:
    
        self.name=name
        self.age=age
        self.phone_number=phone_number
    
The __init__() method is used to create objects of a class. When a new object of a class is created, then this method is automatically called. It accepts a parameter called self which refers to the memory address of this object. It is automatically passed. The init method can accept various values that are assigned to the properties of the object.
To create an object, we do -

p1 = Person("rita",23,98765)
# Prints the memeory address of p1 
print(p1)
Output
<__main__.person object at 0x00000222F3479780>
The class Person has three properties i.e. name, age and phone number. So, we have passed 3 values. To access the properties of an object we can do -

print(p1.name)
print(p1.age)
print(p1.phone_number)
Output
rita
23
98765

The __str__() method

On printing a class object, we get its memory address. But, we can change this behaviour by defining the __str__() method. This method allows us to define a string representation of the class object. If a class has the __str__() method, then the print statement calls it by default for printing the object. Consider the following example.

class Person:

    def __init__(self,name,age,phone_number) -> None:

        self.name=name
        self.age=age
        self.phone_number=phone_number

    def __str__(self):

        return f"My name is {self.name}, age is {self.age} and phone number is {self.phone_number}."
    
p1=Person("rita",23,98765)
print(p1)
    
Output
My name is rita, age is 23 and phone number is 98765.
        

Comparision Methods

By default, if we use the == operator to compare two objects, then the memory address of the two objects are compared. Since p1 and p2 are two different objects, it prints true. But if we compare p1 with itself, then it prints True p1 and p1 are the same object.

p1=Person("rita",23,98765)
p2=Person("rita",23,98765)

print(p1==p2)   # Prints False
print(p1==p1)   # Prints True
print(p2==p2)   # Prints True
But suppose that we want to compare two persons such that two persons are the same if their phone number is same. We can implement this behaviour by defining the __eq__ method(). This method accepts two objects and returns a boolean. Now, if we compare two objects using == then this method is automatically called to provide a way to compare both objects. Consider the following example.

class Person:

    def __init__(self,name,age,phone_number) -> None:

        self.name=name
        self.age=age
        self.phone_number=phone_number

    def __repr__(self):

        return f"My name is {self.name}, age is {self.age} and phone number is {self.phone_number}"

    def __eq__(self, other:object) -> bool:

        # if phone_number of self and other are same, return True, otherwise return False
        return self.phone_number==other.phone_number
    
p1=Person("rita",23,98765)
p2=Person("rita",23,98765)
p3=Person("vaibhav",26,65782)

print(p1==p2)         # Prints true
print(p1!=p3)         # Prints false
There are various comparison methods such as :
Method Comparison
__eq__() Equals to
__ne__() Not Equals to
__gt__() Greater than
__lt__() Less than
__ge__() Greater than or equals to
__le__() Less than or equals to
If we have defined the __eq__() method, then we don't need to define the __ne__() method. Since, if we want to check whether two objects are not the same, then we check if they are the same. If they are the same, return False, otherwise return True. Similarly for the __gt__(), __lt__() methods and the __le__(), __ge_() methods.

Arithmetic Methods

Suppose that we want to implement a behaviour such that when we use the add operator with the Person class object, it performs addition on the age property. It can be done by implementing the __add__() method which accepts the value to be added to the object and then returns the updated object. Consider the below code.

class Person:
    def __init__(self,name,age,phone_number) -> None:

        self.name=name
        self.age=age
        self.phone_number=phone_number

    def __repr__(self):

        return f"My name is {self.name}, age is {self.age} and phone number is {self.phone_number}"

    def __add__(self,value):

        self.age+=value
        return self

p1=Person("rita",23,98765)
p1+=2

print(p1)
    
Output
My name is rita, age is 25 and phone number is 98765
        
Similarly, we can use the __sub__() and the __mul__() method for subtraction and multiplication.