Object-Oriented Programming (OOP) in Python

Python inherently an object-oriented programming language, which makes it easy to work with classes and objects in Python.

Object-oriented programming is an example of a programming paradigms, which are a way to distinguish between different programming languages. Languages can belong to multiple paradigms.

In this tutorial, you will learn about object-oriented programming (OOP) in Python. We’ll discuss the broad characteristics of object-oriented programming as well as several examples of how you can implement this paradigm in practice.

Table of Contents

You can skip to a specific section of this Python tutorial using the table of contents below:

What is Object-Oriented Programming?

Object-oriented programming is a powerful way to bundle your program into classes, instances, and objects. It is widely used for creating powerful and reliable applications. OOP also promotes software maintainability, which leads to better quality of code that is extensible with new attributes and functions.

Learning object-oriented programming can be a challenge for novice developers due to its complexity. It is also computationally intensive and consumes more memory than other paradigms. However, learning OOP is necessary for developers building modern and complex applications.

The relation between classes and objects can be best understood by an example. Consider a class named vehicle. It would be a generic template that has the attributes of tires, color, vehicle_type, and company. An object of the class vehicle, could be a toyota and would have specific values for the attributes, which in this case could be 4, red, sedan, and toyota.

As you can see, object-oriented programming allows programmers to model real-life situations and objects. This is why OOP is so successful in the programming world.

Python is a multi-paradigm language and supports OOP and other paradigms. It is up to the discretion of the developer to select the most appropriate paradigm. Developers can choose to work with only one paradigm or multiple paradigms depending on their requirements.

OOP in Python

Python is a very powerful programming language. It is heavily supported by a robust community, has an easy-to-understand syntax, is dynamically-typed, and has high-level data types.

Being of dynamic nature, developers can choose not to declare the types of variables and arguments when creating them. These properties of python enable faster development and make the code much more readable.

Python’s primitive data types (like lists, dictionaries and tuples) allow you to store simple data conveniently.

However, what if there is a more complex problem?

Imagine keeping a record of people where each person has a name, gender, age and other properties. It becomes difficult to store this information in primitive data types alone.

This is why we use classes. In this case, you’d create a class called person. It will contain the arbitrary information that is common for all people, like name, gender, and age.

The class acts like a blueprint. It does not contain actual information. To use classes, you create objects using this blueprint. This creates an instance of that class.

In the next section, we’ll create a class, define its attributes and create its objects.

Creating a Class

Now that you know the relation between classes and objects, you can go ahead and create classes in Python. It’s fairly simple and similar to the syntax used to create Python functions.

As an example, here’s how you would create a class called Vehicle:

class Vehicle:


    def __init__(self):
        pass        

To define a class, you start with the keyword class, followed with the name of the class. Conventionally, CamelCase approach is followed to name the classes, starting with a capital letter.

This code creates a basic class. The ___init__(self) method has to be defined inside each class. It later helps when creating instances of that class.

The keyword pass allows us to run this code without an error. pass is a null statement and is typically used as a placeholder, indicating that the code will be written in the future.

We will be dealing with the vehicle class for the remainder of this tutorial. We will create instances of this class to help you better understand OOP in Python.

Now let’s see how you can create attributes of the class that was just created.

Creating Attributes

A class is an abstraction which is later implemented by the objects of the class. Each object has a set of characteristics defined by the class. These characteristics are known as attributes.

Here’s how you create attributes within our Vehicle class:

class Vehicle:


    horn = "honk honk"
    def __init__(self, tires, color, vehType, company):
        self.tires = tires
        self.color = color
        self.type = vehType
 	      self.company = company

Here, we’ve defined the class vehicle, which has the attributes of horn, tires, color, and vehType.

horn is a pre-initialized attribute that the user will not have to set while creating an object. These attributes are known as class attributes and hold the same value for all instances of the class. The developer can change the value of class attributes if required.

The rest of the attributes need to be initialized while creating an object. These are known as instance attributes.

The self variable is a special instance of the class, through which you can access the attributes and methods of the class. It binds the attributes with the given arguments.

Now let’s create some Vehicle objects. Said differently, we will now create some instances of the Vehicle class.

Instantiating Objects

Instantiating is the technical term for creating an object for a class. These objects are the useful representation of the class. In other words, classes usually can’t serve a practical purpose until you use them to create objects.

In the following code block, two Vehicle objects are initialized and their details are printed out.

class Vehicle:


    horn = "honk honk"
    def __init__(self, tires, color, vehType, company):
        self.tires = tires
        self.color = color
        self.type = vehType
        self.company = company

chevy = Vehicle(4, "RED", "TRUCK", "CHEVY")
ford = Vehicle(4, "BLUE", "TRUCK", "FORD")

print("This is my "+ chevy.color + " " + chevy.company + " " + chevy.type + " it has " +  str(chevy.tires) + " tires.")
print("This is my "+ ford.color + " " + ford.company + " " + ford.type + " it has " +  str(ford.tires) + " tires.")

Notice the print statement. Here you access the different properties of the objects via the dot operator. This way, you can access the desired properties and print out a meaningful sentence.

Save this code as classTest.py and execute it. You should get the following results:

C:\Users\Python> python classTest.py
This is my RED CHEVY TRUCK it has 4 tires.
This is my BLUE FORD TRUCK it has 4 tires.

Let’s see what happens when an object of a class is created. In this example, a new instance of the Vehicle class is created and is assigned to variable chevy. The attribute values are passed in as arguments.

These values are then processed by the init function, which gets called when you create a new object. We do not pass anything for the self argument because python determines the object to be a Vehicle automatically and proceeds with the function, assigning the values.

Class Methods

Methods or functions are defined inside of the class and are used to access the value of attributes and or perform operations on their values. Just like the init function, all methods starts with the keyword def followed by the name of the function. The first argument of a class method is always self.

Here’s an example of a simple method created for the Vehicle class that represents the horn of a vehicle.

class Vehicle:


    horn = "honk honk"
    def __init__(self, tires, color, vehType, company):
        self.tires = tires
        self.color = color
        self.type = vehType
        self.company = company

    def honk(self):
        print(horn)

chevy = Vehicle(4, "RED", "TRUCK", "CHEVY")
chevy.honk()

When this code is executed, you’ll get the following output:

C:\Users\Python> python classTest.py
honk honk

You could also create a method to change the color of the vehicle.

class Vehicle:


    horn = "honk honk"
    def __init__(self, tires, color, vehType, company):
        self.tires = tires
        self.color = color
        self.type = vehType
        self.company = company

    def honk(self):
        print("honk honk")


    def paintShop(self, color):
        self.color = color

chevy = Vehicle(4, "RED", "TRUCK", "CHEVY")

print("This is my "+ chevy.color + " " + chevy.company + " " + chevy.type + " it has " +  str(chevy.tires) + " tires.")

chevy.paintShop("PURPLE")

print("My Chevy's new color is: " + chevy.color)

When this code is executed, you’ll get the following output:

C:\Users\Python> python classTest.
This is my RED CHEVY TRUCK it has 4 tires.
My Chevy's new color is: PURPLE

In the code, the color attribute of the chevy truck object is updated and printed. Methods reduce repetition in code, improving readability and making development faster.

Class Inheritance

Inheritance is a very important concept of the object-oriented programming paradigm. It is the process by which a child class can inherit attributes and methods of a parent class.

The child classes override or extend the functionality offered by the parent class. This means that the child class has all the attributes and methods of the parent class, but can also specify different behavior as well.

In Python, all base classes are generally inherited from an object class. In Python 3, when you define a class, it is implicitly inherited from the object class.

This means that the following two declarations are equivalent:

class Vehicle(object):
    pass
#Python 3 does this implicitly 
class Vehicle:
    pass

Now let’s try inheritance with the Vehicle class that we built earlier in this tutorial.

Child Class: Bike

We can inherit another class from the Vehicle class to specify a special vehicle. In the code ahead, a Bike class is created, which is a child class of Vehicle.

class Bike(Vehicle):
    def __init__(self, color, company):
        self.tires = 2
        self.color = color
        self.type = "motorcycle"
        self.company = company
    def honk(self):
        print("peep peep")

honda = Bike("GREEN", "HONDA")
print("My bike honks like: " + honda.horn)
honda.honk()

Since all bikes have the vehicle type motorcycle, it is hardcoded into the class. The same logic applies for the tires attribute. We have also updated the horn function of the Bike class.

The Bike class is inherited from the Vehicle class but the fields have been updated to meet the specific requirements of a motorcycle.

This code generates the following output:

C:\Users\Python> python classTest.py
My bike honks like: honk honk
peep peep

This is inheritance in action. since the horn attribute is defined in the Vehicle attribute as “honk honk” and is not overridden in the Bike child class, it outputs “honk honk” in the first line.

However, as the honk function is overridden, it shows the output of the Bike child class instead of the Vehicle parent class’ honk function.

Final Thoughts

Learning object-oriented programming is a requirement for any serious developer. It is implemented in all major programming languages due to its benefits and ability to simplify seemingly complex problems.

OOP allows better structuring of code. Python takes it one step further by using its simple and easy-to-understand syntax. However, it should be noted that OOP is not a unique concept of Python. Instead, it is a programming paradigm, applicable to a variety of programming languages.

Learning OOP will not only improve your Python skills, but will also give you an edge in other languages like Java and C++.

If you enjoyed this article, be sure to join my Developer Monthly newsletter, where I send out the latest news from the world of Python and JavaScript:
Written on May 28, 2020