Object-Oriented Programming, also known as OOPs concepts in python, is what lets us develop applications using an Object-Oriented approach. It does so by clubbing together similar or related behaviors and properties and converting them into objects. In this article, I will explain the basic concepts of Object-Oriented Programming in Python programming, oop fundamentals, and features of oops. You must know Python programming before you continue.
Developers often choose to use OOPs principles in Python programs because it makes code more reusable and easier to work with larger programs. OOP programs prevent you from repeating code because a class can be defined once and reused many times.
Beginners can learn Python using the free course on Introduction to Python.
Learning Objectives
While learning Object-Oriented Programming (oops concepts), I decided to dive into its history to fully know what is oops concept and it turned out to be fascinating. The term “Object-Oriented Programming” (OOP), also known as OOPs principles in python, was coined by Alan Kay around 1966 while he was at grad school. The language called Simula was the first programming language with the features of Object-oriented programming. It was developed in 1967 for making simulation programs, in which the most important information was called objects.
Though OOPs were in the market since the early 1960s it was in the 1990s that OOPs began to grow because of C++. After that, this technique was adopted by various programmers across various programming languages, including Python. Today its application is in almost every field, such as Real-time systems, machine learning, Artificial intelligence, Data Science, expert systems, Client-server systems, Object-oriented databases, and many more.
In Python, OOPs stands for Object-Oriented Programming. It is a programming paradigm that focuses on the use of objects and classes to create programs. An object is a group of interrelated variables and functions. These variables are often referred to as properties of the object, and functions are referred to as the behavior of the objects. These objects provide a better and clear structure for the program. Main principles of OOPs in Python are abstraction, encapsulation, inheritance, and polymorphism.
Abstraction refers to the ability to hide the implementation details of an object from the user, while still providing a simple and easy-to-use interface. Encapsulation refers to the practice of combining data and methods within a class to protect the data from external interference. Inheritance is a way to create new classes based on existing ones, allowing the new classes to inherit the attributes and methods of the parent class. Polymorphism allows you to treat objects of different classes as if they were of the same class. Consequently, you can write generic code that works with a variety of objects.
By using OOPs concepts in Python, developers can create programs that are more modular, flexible, and easier to maintain. OOPs makes it possible to write code that is reusable and scalable, reducing the overall development time and increasing code efficiency.
For example, a car can be an object. If we consider the car as an object, its properties would be its color, model, price, brand, etc. And its behavior/function would be acceleration, slowing down, and gear change.
Another example – If we consider a dog as an object then its properties would be its color, breed, name, weight, etc., and its behavior/function would be walking, barking, playing, etc.
Object-Oriented Programming is famous because it implements real-world entities like objects, hiding, inheritance, etc, in programming. It makes visualization easier because it is close to real-world scenarios.
The basic differences between OOP and POP are the following:
In this section, we will dive deep into the basic concepts of object oriented programming Tutorial. Here is list of OOP’s concepts given below:
A straightforward answer to this question is- A class is a collection of objects. Unlike primitive data structures, classes are data structures that the user defines. They make the code more manageable.
Let’s see how to define a class below-
class class_name:
class body
We define a new class with the keyword “class” following the class_name and colon. And we consider everything you write under this after using indentation as its body. To make this more understandable, let’s see an example.
Consider the case of a car showroom. You want to store the details of each car. Let’s start by defining a class first-
class Car:
pass
That’s it!
Note: I’ve used the pass statement in place of its body because the main aim was to show how you can define a class and not what it should contain.
Even the datatypes in Python, like tuples,dictionaries, etc. are classes.
Before going into detail, first, understand objects and instantiation.
When we define a class, only the description or a blueprint of the object is created. There is no memory allocation until we create its object. The objector instance contains real data or information.
Instantiation is nothing but creating a new object/instance of a class. Let’s create the object of the above class we defined-
obj1 = Car()
And it’s done! Note that you can change the object name according to your choice.
Try printing this object-
print(obj1)
Since our class was empty, it returns the address where the object is stored i.e. 0x7fc5e677b6d8
You also need to understand the class constructor before moving forward.
Until now, we have had an empty class Car, time to fill up our class with the properties of the car. The class constructor assigns values to the data members when you create an object of the class.
There can be various properties of a car, such as its name, color, model, brand name, engine power, weight, price, etc. We’ll choose only a few for understanding purposes.
class Car:
def __init__(self, name, color):
self.name = name
self.color = color
So, the properties of the car or any other object must be inside a method that we call __init__( ). We also know this __init__()
method as the constructor method. We call the constructor method whenever we construct an object of the class.
Now let’s talk about the parameter of the __init__() method. So, the first parameter of this method has to be self. Then only will the rest of the parameters come.
The two statements inside the constructor method are –
This will create new attributes, namely name and color, and then assign the value of the respective parameters to them. The “self” keyword represents the instance of the class. By using the “self” keyword, we can access the attributes and methods of the class. It is useful in method definitions and in variable initialization. The “self” is explicitly used every time we define a method.
Note: You can also create attributes outside of this __init__() method. But those attributes will be universal to the whole class, and you will have to assign a value to them.
Suppose all the cars in your showroom are Sedan, and instead of specifying it again and again, you can fix the value of car_type as Sedan by creating an attribute outside the __init__().
class Car:
car_type = "Sedan" #class attribute
def __init__(self, name, color):
self.name = name #instance attribute
self.color = color #instance attribute
Here, Instance attributes refer to the attributes inside the constructor method, i.e., self.name and self.color. And Class attributes refer to the attributes outside the constructor method, i.e., car_type.
So far, we’ve added the properties of the car. Now it’s time to add some behavior. Methods are the functions we use to describe the behavior of objects. They are also defined inside a class. Look at the following code-
Python Code:
#You can play around with the properties of the car and also add and remove some properties in the code block down below
class Car:
car_type = "Sedan"
def __init__(self, name, mileage):
self.name = name
self.mileage = mileage
def description(self):
return f"The {self.name} car gives the mileage of {self.mileage}km/l"
def max_speed(self, speed):
return f"The {self.name} runs at the maximum speed of {speed}km/hr"
obj2 = Car("Honda City",24.1)
print(obj2.description())
print(obj2.max_speed(150))
We know the methods defined inside a class, other than the constructor method, as instance methods. Furthermore, we have two instance methods here – description() and max_speed(). Let’s talk about them individually:
Notice that the additional parameter speed is not using the “self” keyword. Since speed is not an instance variable, we don’t use the self keyword as its prefix. Let’s create an object for the class described above.
obj2 = Car("Honda City",24.1)
print(obj2.description())
print(obj2.max_speed(150))
We created an object of the class Car and passed the required arguments. To access the instance methods, we use object_name.method_name().
The method description() didn’t have any additional parameter, so we did not pass any argument while calling it.
The method max_speed() has one additional parameter, so we passed one argument while calling it.
Note: Three important things to remember are-
Let’s look at these, one by one:
class Car:
def __init__(self, name, mileage):
self.name = name
self.mileage = mileage
def max_speed(self, speed):
return f"The {self.name} runs at the maximum speed of {speed}km/hr"
Honda = Car("Honda City",21.4)
print(Honda.max_speed(150))
Skoda = Car("Skoda Octavia",13)
print(Skoda.max_speed(210))
class Car:
def __init__(self, name, mileage):
self.name = name
self.mileage = mileage
Honda = Car("Honda City")
print(Honda)
Since we did not provide the second argument, we got this error.
class Car:
def __init__(self, name, mileage):
self.name = name
self.mileage = mileage
def description(self):
return f"The {self.name} car gives the mileage of {self.mileage}km/l"
Honda = Car(24.1,"Honda City")
print(Honda.description())
Messed up! Notice we changed the order of arguments.
There are four fundamental concepts of Object-oriented programming – Inheritance, Encapsulation, Polymorphism, and Data abstraction. It is essential to know about all of these in order to understand OOPs. Till now, we’ve covered the basics of OOPs concepts in python; let’s dive in further.
Inheritance is the procedure in which one class inherits the attributes and methods of another class. The class whose properties and methods are inherited is known as the Parent class. And the class that inherits the properties from the parent class is the Child class.
The interesting thing is, along with the inherited properties and methods, a child class can have its own properties and methods.
How to inherit a parent class? Use the following syntax:
class parent_class:
body of parent class
class child_class( parent_class):
body of child class
Let’s see the implementation:
class Car: #parent class
def __init__(self, name, mileage):
self.name = name
self.mileage = mileage
def description(self):
return f"The {self.name} car gives the mileage of {self.mileage}km/l"
class BMW(Car): #child class
pass
class Audi(Car): #child class
def audi_desc(self):
return "This is the description method of class Audi."
obj1 = BMW("BMW 7-series",39.53)
print(obj1.description())
obj2 = Audi("Audi A8 L",14)
print(obj2.description())
print(obj2.audi_desc())
We have created two child classes, namely “BMW” and “Audi,” who have inherited the methods and properties of the parent class “Car.” We have provided no additional features and methods in the class BMW. Whereas one additional method inside the class Audi.
Notice how the instance method description() of the parent class is accessible by the objects of child classes with the help of obj1.description() and obj2.description(). The separate method of class Audi is also accessible using obj2.audi_desc().
Encapsulation, as I mentioned in the initial part of the article, is a way to ensure security. Basically, it hides the data from the access of outsiders. Such as, if an organization wants to protect an object/information from unwanted access by clients or any unauthorized person, then encapsulation is the way to ensure this.
You can declare methods or attributes as protected by using a single underscore (_) before their names, like _self.name or def _method(). Both lines indicate that the attribute and method are protected, accessible only within the class and subclasses, but can be accessed by class methods and objects.
Though Python uses ‘ _ ‘ just as a coding convention, it tells that you should use these attributes/methods within the scope of the class. But you can still access the variables and methods which are defined as protected, as usual.
Now to actually prevent the access of attributes/methods from outside the scope of a class, you can use “private members“. In order to declare the attributes/method as private members, use double underscore ( ) in the prefix. Such as – self.name or def __method(); Both of these lines tell that the attribute and method are private and access is not possible from outside the class.
class car:
def __init__(self, name, mileage):
self._name = name #protected variable
self.mileage = mileage
def description(self):
return f"The {self._name} car gives the mileage of {self.mileage}km/l"
obj = car("BMW 7-series",39.53)
#accessing protected variable via class method
print(obj.description())
#accessing protected variable directly from outside
print(obj._name)
print(obj.mileage)
Notice how we accessed the protected variable without any error. It is clear that access to the variable is still public. Let us see how encapsulation works
class Car:
def __init__(self, name, mileage):
self.__name = name #private variable
self.mileage = mileage
def description(self):
return f"The {self.__name} car gives the mileage of {self.mileage}km/l"
obj = Car("BMW 7-series",39.53)
#accessing private variable via class method
print(obj.description())
#accessing private variable directly from outside
print(obj.mileage)
print(obj.__name)
When we tried accessing the private variable using the description() method, we encountered no error. But when we tried accessing the private variable directly outside the class, then Python gave us an error stating: car object has no attribute ‘__name’.
You can still access this attribute directly using its mangled name. Name mangling is a mechanism we use for accessing the class members from outside. The Python interpreter rewrites any identifier with “__var” as “_ClassName__var”. And using this you can access the class member from outside as well.
class Car:
def __init__(self, name, mileage):
self.__name = name #private variable
self.mileage = mileage
def description(self):
return f"The {self.__name} car gives the mileage of {self.mileage}km/l"
obj = Car("BMW 7-series",39.53)
#accessing private variable via class method
print(obj.description())
#accessing private variable directly from outside
print(obj.mileage)
print(obj._Car__name) #mangled name
Note that the mangling rule’s design mostly avoids accidents. But it is still possible to access or modify a variable that is considered private. This can even be useful in special circumstances, such as in the debugger.
This is a Greek word. If we break the term Polymorphism, we get “poly”-many and “morph”-forms. So Polymorphism means having many forms. In OOPs principles it refers to the functions having the same names but carrying different functionalities.
class Audi:
def description(self):
print("This the description function of class AUDI.")
class BMW:
def description(self):
print("This the description function of class BMW.")
audi = Audi()
bmw = BMW()
for car in (audi,bmw):
car.description()
When you call the function using the object audi, it calls the function of class Audi. Similarly, when you call it using the object bmw, it calls the function of class BMW.
We use Abstraction for hiding the internal details or implementations of a function and showing its functionalities only. This is similar to the way you know how to drive a car without knowing the background mechanism. Or you know how to turn on or off a light using a switch, but you don’t know what is happening behind the socket.
Any class with at least one abstract function is an abstract class. To create an abstraction class, first, you need to import the ABC class from abc module. This lets you create abstract methods inside it. ABC stands for Abstract Base Class.
from abc import ABC
class abs_class(ABC):
Body of the class
The important thing is – you cannot create an object for the abstract class with the abstract method. For example-
from abc import ABC, abstractmethod
class Car(ABC):
def __init__(self,name):
self.name = name
@abstractmethod
def price(self,x):
pass
obj = Car("Honda City")
Now the question is, how do we use this abstraction exactly? The answer is, by using inheritance.
from abc import ABC, abstractmethod
class Car(ABC):
def __init__(self,name):
self.name = name
def description(self):
print("This the description function of class car.")
@abstractmethod
def price(self,x):
pass
class new(Car):
def price(self,x):
print(f"The {self.name}'s price is {x} lakhs.")
obj = new("Honda City")
obj.description()
obj.price(25)
Car is the abstract class that inherits from the ABC class from the abc module. Notice how I have an abstract method (price()) and a concrete method (description()) in the abstract class. This is because the abstract class can include both of these kinds of functions, but a normal class cannot. The other class inheriting from this abstract class is new(). This method defines the abstract method (price()), which is how we use abstract functions.
After the user creates objects from the new() class and invokes the price() method, the definitions for the price method inside the new() class comes into play. These definitions are hidden from the user. The Abstract method is just providing a declaration. The child classes need to provide the definition.
But when the description() method is called for the object of the new() class, i.e, obj, the Car’s description() method is invoked since it is not an abstract method.
Dynamic binding (or late binding) means deciding which method to call when the program runs, not when the code is written. This makes your code more flexible because the exact method to run is chosen based on the object type at runtime.
Example:
class Car:
def start_engine(self):
raise NotImplementedError("Subclass must implement this method")
class Honda(Car):
def start_engine(self):
return "The Honda engine has started."
class BMW(Car):
def start_engine(self):
return "The BMW engine has started."
def start_car_engine(car):
print(car.start_engine())
honda_car = Honda()
bmw_car = BMW()
start_car_engine(honda_car) # Output: The Honda engine has started.
start_car_engine(bmw_car)
# Output: The BMW engine has started.
In this example, the start_engine() method is chosen based on whether the object is a Honda or a BMW when the program runs. This shows dynamic binding in action because the method that gets called depends on the actual object type at runtime.
Message passing is how objects talk to each other in object-oriented programming. One object sends a message (calls a method) to another object to make it do something or to get some information.
class Car:
def __init__(self, brand):
self.brand = brand
def start_engine(self):
print(f"The {self.brand} engine has started.")
class Driver:
def __init__(self, name):
self.name = name
def drive(self, car):
print(f"{self.name} is driving the car.")
car.start_engine()
car = Car("Toyota")
driver = Driver("John")
driver.drive(car)
In this example, the Driver object sends a message to the Car object by calling its start_engine method through the drive method. This shows how objects interact by sending messages to each other.
We’ve now covered the basic concepts of Object-Oriented Programming (OOP) in this Python tutorial. In Python, object-oriented Programming (OOPs) is a programming paradigm that uses objects and classes in programming. OOPs, concepts in python, aim to implement real-world entities like inheritance, polymorphisms, encapsulation, etc., in the programming.
Here are some articles you can read to learn more about Python:
Key Takeaways
A. The OOP concept revolves around designing software using objects, which represent real-world entities. Moreover, it organizes code by grouping related properties and behaviors into these objects.
A. In object-oriented programming, you create classes to define objects. For example, you might define a Car
class with attributes like color
and model
, and methods like drive()
and stop()
. Then, you instantiate objects such as myCar
from this class.
A. The four basics of OOP include encapsulation, inheritance, polymorphism, and abstraction. First, encapsulation bundles data and methods. Next, inheritance allows new classes to derive from existing ones. Then, polymorphism enables objects to be treated as instances of their parent class. Finally, abstraction simplifies complex systems by modeling classes appropriate to the problem.
A. OOPs, or Object-Oriented Programming System, includes features like encapsulation, inheritance, polymorphism, and abstraction. Additionally, these features help you create modular, reusable, and scalable code, making software development more efficient and manageable.
Hi. I am 12 year old kid . It's great way to learn coding through these small and easy methods .
Thanks Kaustav! Really good to hear this. Happy learning!!
I want to be programmer, this site may be helpful me
# Bug Under:- 5. Encapsulation --> Mangled name when you are calling a private member using the mangled name, the class name starts with the capital letter 'Car', not 'car'. Last line under encapsulation-> print(obj._car__name) #mangled name -------------------- Rest article was very good and to the point.
Thanks for pointing that out, Rajesh. I've made the necessary change.
On the line after the Hexadecimal number, you mention a class conductor? Should that say constructor?
Thanks for pointing that out!
Very nice way of writing. Thank You
Thanks a lot, glad you liked it!
class class_name: class body We define a class with a keyword “class” following the class_name and semicolon. correction: colon (:), not semi-colon (;)
Thanks a lot!
This the best explanation and easy to understand,lot of grattitude to you :)
Thanks Baljeet, made my day!
Hello ma'am..Really I found this article very helpful and thanks for explaining in detail with the examples .
Thanks for reading!
Thanks for sharing! Really informative and helpful blog.
Thanks for reading :)
Thanks for sharing! Really informative and helpful blog. Helped me alot.
Thanks for reading :)
Thanks for sharing! Really informative and helpful blog. Helped me alot.
great explanation!!!!!!
Great nice content
Thanks for reading :)
Very nice explanation and easy to understand. Thanks to you.
Thanks for reading :)