This article was published as a part of the Data Science Blogathon.
Object-Oriented Programming or OOP. Whenever we see this term, we associate this with Java programming languages. It is a fact that java popularized an object-oriented style of programming but is it the only language out there to have OOP?
Definitely not. For Python fans like us, Python does offer an object-oriented style of programming.
In this blog, we will be learning everything that we need to know for object-oriented programming in Python. At the same time, we will also be implementing those object-oriented concepts in Python as well.
For learning the crux of Object-Oriented Programming in Python, We will be learning the following topics in this article both the theory part and implementation part.
Topics to be covered:-
Let’s embark on our journey of learning OOP in Python!
NOTE:- For the rest of the remaining part of the article, I will be referring to Object-Oriented Programming by abbreviation OOP.
In this article, since we are going to implement those concepts as well here are the pre-requisites:-
Here I will be implementing all those concepts in the Jupyter notebook in Ubuntu 20.04.2 LTS. Again a selection of OS does not affect as it is a personal preference. All the concepts that we are going to learn will be similar irrespective of the operating system used.
What are classes in OOP? Let’s understand this concept easily with the help of a picture.
If we analyze the above image, we are seeing class, object, attributes, methods, and a Pikachu there :). You might be thinking about what all of this has to do with OOP. Well, the above image is exactly what we need to understand OOP concepts easily.
So moving to the first topic. What is meant by class in OOP? The technical definition of class is “Class is a collection of an object of the same type“.Let’s relate this to our example above.
Here in this image, we can see there is a rectangle name “Pokemon”. This is basically the name of our class. In the simplest term class is nothing but a collection of objects. So all the pokemon in the pokemon universe will be under the “pokemon” class.
In OOP, an object is basically a constituent or member of a class. Taking into consideration our pokemon example, each pokemon is an object of the Pokemon class. For example. Pikachu is an object of Pokemon class.
Back to our Pokemon example. Let’s focus on Pikachu in the image. Just observed it for a moment. What are you seeing?
Just by looking at an image of Pikachu, we can see that it has two ears, two hands, two legs, two small red-coloured dots on cheeks, and a distinguishing yellow colour. In addition to that in the adjoining table in the image, we are seeing few more things like Name = “Pikachu”, Type = “Electric” and Health = 70. So all are those are known as attributes. Attributes are elements that provide extra information about classes or objects. In this case, all those attributes are providing additional information about the Pikachu object like colour, health type, etc.
In our example, under the bottom three lines, we are seeing something like attack(), dodge(), and evolve(). Those are known as methods. To explain it more simply, methods are basically actions that are associated with a particular object. In this case, those actions as associated with our Pikachu object.
Now till this point, we have a theoretical understanding of various object-oriented concepts in Python. Now let’s implement those concepts in python using the jupyter notebook.
Here I am going to implement those concepts using Jupyter notebook in Ubuntu 20.04.2 LTS but. Again the choice of OS is a personal preference as all the concepts that we are seeing here will be similar across any platform.
Let’s start implementing OOP concepts in Python. Here we will be coding using a jupyter notebook. Again the choice of IDE is a personal preference. Being a data scientist I have spent most of my time using jupyter notebook and hence I am using the same here for OOP as well.
Let’s create our class named “Pokemon” in python.
#Creating class named "Pokemon" class Pokemon():
As you can see from the code above, there is a certain structure that needs to be followed while creating a class in python. The convention is to start with the keyword named “class”. In this way, python can recognize that whatever we are trying to create is going to be considered a class. The keyword class is then followed by the class name which is Pokemon in this case. Eventually, it is followed ( ) which then again followed by “:” character.
Now you might have a question – “is our class creation completed ?”.Well not yet. There are still some lines of code that we need to write down in our class to complete its creation.
Continuing with our class creation task, the next step involved the creation of a very special method named “__init__”. You might ask “What is this __init__ method and why it is called so?”. Well to understand this concept easily, consider the init method similar to the main method in Java.
If we analyze any java code, we can that with every class there is the main method associated. The same is the concept in Python as well. Here instead of calling it the “main” method, it is known as the “__init__” method. Let’s add this code to our class.
#Creating class named "Pokemon" class Pokemon(): def __init__():
As you can see from the code above, here we have created our __init__ method in Python. Here we are noticing one thing which is the keyword named “def”.What is the purpose of this def keyword here? Basically def is a keyword in python that we use specifically which defining method for an object.
Also here you are noticing one thing. By default, python is aligning some indentation in the code that we are writing. We are witnessing what is known as “Syntax Engine” in python. This syntax engine operates on its own. Its main purpose is to make our code look neat and clean.
Since we have defined our __init__( ) method for our class, it’s still not completely defined. Still, certain arguments need to be passed in the __init__( ) method to complete its definition.Let’s add those arguments in our __init__( ) method.
#Creating class named "Pokemon" class Pokemon(): def __init__(self,name,Type,health): self.name = name self.Type = Type self.health = health
As you can see from the code above, we have passed lots of arguments in our __init__( ) method. Now let’s backtrack a little to understand what parameters are being passed here.
Remember a little while ago, we discussed that our Pikachu is having yellow colour, two red dots on cheeks, etc. Well, those are basically attributes associated with an object and in this __init__ ( ) method we are simply passing defining those attributes.
You might be having another question now – “What is the use of keyword self and what is the below self. line of codes doing?”. To explain this in simple terms, “self” is basically a keyword that is responsible for connecting those attributes to our class which is pokemon in this case.
Below 3 lines of codes “self…” are responsible for connecting those attributes to our class. Now let’s proceed to further part
Till this point, we have declared our class, special method named __init__ ( ) and attributes for the class. Now let’s proceed with our final part which is method creation.
def attack(self): print("Electric attack!!.Zhoop!!!")
As you can see from the code above, we are creating a method named attack() here. If you observed this piece of code carefully, you can see that for this method we have passed an argument named “self” here. The reason for this is the same again. Here we are connecting this method to our class using the self keyword.
If you see our example image above, with our Pokemon class there are three methods associated – attack(), Dodge(), Evolve(). Here since we have already created our attack() method, let’s incorporate the remaining two methods in our class.
Once we incorporate all those changes, our final Pokemon class will look like this
#Creating class named "Pokemon" class Pokemon(): def __init__(self,name,Type,health): self.name = name self.Type = Type self.health = health def attack(self): print("Electric attack!!.Zhoop!!!") def dodge(self): print("Pikachu Dodge!") def evolve(self): print("Evolving to Raichu!!!!")
Now the only thing remaining is to execute our line of code and we are done with class creation. Once this line of code is executed, you will see something like this in a jupyter notebook.
The next part of our OOP journey is to create an instance of a class that is basically an object.
Now let’s continue with the creation of an object in Python.
#Creating object of "Pokemon" class pk1 = Pokemon("Pikachu","Electric",120)
Here you can see that we have created an object named pk1.
Attributes associated with an object can be accessed by using. (Dot) operators. Let’s access all attributes associated with our pk1 object in the jupyter notebook.
#Creating class named "Pokemon"
class Pokemon():
def __init__(self,name,Type,health):
self.name = name
self.Type = Type
self.health = health
def attack(self):
print("Electric attack!!.Zhoop!!!")
def dodge(self):
print("Pikachu Dodge!")
def evolve(self):
print("Evolving to Raichu!!!!")
#Creating object of "Pokemon" class
pk1 = Pokemon("Pikachu","Electric",120)
print(pk1.name)
In the above code, we can see that we have accessed the name attribute associated with our pk1 object. In the same manner, let’s access all attributes associated with our object.
#Accessing Type attribute of pk1 object pk1.Type
Output:
'Electric'
We can also access methods associated with our object using the dot operator. So let’s quickly access all methods associated with our pk1 object.
pk1.attack()
Output:
Electric attack!!.Zhoop!!!
#Accessing evolve() method of pk1 object pk1.evolve()
Output:
Evolving to Raichu!!!!
#Accessing dodge() method of pk1 object pk1.dodge()
Output:
Pikachu Dodge!
Here one important thing to note is that while accessing methods associated with our object, we need to put () after the method name.
Inheritance is one of the key concepts in OOP. Let’s understand this concept easily with the help of a simple example.
Let’s consider an example of a supercar ex. McLaren 720S spyder. It’s basically a supercar. For those of you interested in cars, this is what I am talking about.
As you can see, like most other cars it is having some common characteristics like doors, windshield, 4 wheels, headlights, taillights, etc. However, since it is a supercar, it is having its own custom features like the 720 Horsepower V8 turbocharged engine, a custom-made gearbox developed by McLaren, and a customized AWD(All-wheel Drive) system.
Now relating this to Object-oriented terminology, we can say that this car is inheriting a certain feature from its parent class which will be a car class in this case. And that is the concept behind Inheritance.
Inheritance is basically a phenomenon where an element acquires characteristics from its parent class. So in this case our McLaren 720S spyder is inheriting all common features from car class but at the same time, it itself is having certain special features.
The class from which our element is inheriting (Car class in this case) is known as Superclass and it is generic in nature. While the class which is inheriting those characteristics is known as sub-class which is specific in nature.
Let’s implement those concepts in Python now. In this case m, we will create two classes – One is going to be a class named “Car” and is going to be our superclass. Another class is going to be a class named “McLaren” and is going to be our subclass. This “McLaren” class will inherit all properties of the “Car” class.
class Car(): def __init__(self,ndoors,nwheels,tailLight,headLight): self.ndoors = ndoors self.nwheels = nwheels self.tailLight = tailLight self.headLight = headLight
Here we have created our first class named “Car”. Now we are going to create our new class named “McLaren” which is going to inherit all attributes of this class
Creation of McLaren class in Python:
class McLaren(Car): def __init__(self,ndoors,nWheels,tailLight,headLight,Engine,Wheel_Drive): Car.__init__(self,ndoors,nWheels,tailLight,headLight) self.Engine = Engine self.Wheel_Drive = Wheel_Drive def Drive(self): print("I am driving McLaren 720S Spyder")
As you can see in this code above, since our McLaren class is inheriting the Car class, we have mentioned Car as one of the parameters while creating our McLaren class and this basically represents this inheritance mechanism in Python.
Now it’s time to test our theory about whether our McLaren class is inheriting features of the Car class or not.
#Creating an object of McLaren Class mk1 = McLaren("4","4","Yes","Yes","V8","AWD")
Now let’s try to access attribute which is specific to McLaren class
Code For Accessing engine attribute of McLaren class:
#Aceesing Engine attribute for McLaren Class mk1.Engine
Output:
'V8'
#Accessing Wheel_Drive attribute for McLaren Class mk1.Wheel_Drive
Output:
'AWD'
Here we can see that we are able to access attributes that are specific to the McLaren object. Since here we are inheriting our base class which is Car class in this case, let’s see if those attributes from the base class have been inherited or not in our McLaren class.
Code For Accessing inherited attributes:
headLight inherited attributes:
mk1.headLight
Output:
Yes'
mk1.ndoors
Output:
'4'
Accessing nwheels inherited attribute:
mk1.nwheels
Output:
'4'
Accessing tailLight attribute:
mk1.tailLight
Output:
'Yes'
As we can see here, our newly created object of McLaren class is inheriting all features of the Car base class indicating that inheritance is being implemented correctly in this context.
And that’s it. We have now covered all the topics that one must need to know about object-oriented programming in Python.
Do let me know how you feel about this post
The media shown in this article are not owned by Analytics Vidhya and is used at the Author’s discretion.
Waoh!!!! This is incredible. OOP can be a nightmare if you don't get it right. As a self taught programmer, got the hard part of super/subclass. Normally this part is abstract to beginners. You also touched on generic Though very far. Maybe I pray you write more on that and bring out the elephant. This will really help because of your beginner friendly approach.
Amazing.. Very easy to understand.. We can easily connect to both the examples!
What a beautiful article. You made Python OOP so easy to grasp. Thank you so much!