Understand O.O.P. in Python with One Article
By: Julian Herrera
Tags: Programming, Python, Object Oriented, Learning To Code, Data Science

1. Introduction to Object-oriented programming

In order to begin understanding the intuition behind this programming technique, let’s take a look at an initial example. Imagine that you have to describe a car to someone who’s never seen one before, how would you do it?

Photo by vaea Garrido on Unsplash

You might want to start saying that it’s a wheeled motor vehicle used for transportation. Also, you might say that there are several brands of car-maker companies, which make different types of cars that fulfill various needs. In an even more basic level you might say that it has four tires, that they carry up to five people in most cases and that they are mainly used to transport people, not goods.

When explaining to a computer what kind of object this is, it’s a good idea to approach it in a similar way. Computers have no innate idea of what a car is, why were they created or who uses them. And if you want your computer to correctly understand the object, a car in this case, you have to clearly explain which are its attributes.

To make it easier for computers to understand these new concepts, Python uses a programming pattern called object-oriented programming, which models concepts using classes and objects. This is a flexible, powerful paradigm where classes represent and define concepts, while objects are instances of classes. In the car example, we can create a class called car that defines its characteristics to the computer. We would be able to create thousands of instances of that class car, which are the individual objects of that class.

The idea of object-oriented programming might sound abstract and complex, but if you’ve programmed any software you might have already used objects without even realizing it. Almost everything in Python is an object, all of the numbers, strings, lists, and dictionaries are included in this type of element. The core concept of object-oriented programming comes down to attributes and methods associated with a type:

Attributes are the characteristics associated to a type.

are the characteristics associated to a type. Methods are the functions associated to a type.

In the car example, color and brand are two attributes associated with every instance, or car, created with the program. On the other hand, methods would be actions performed with or by the car, such as driving. A more computer-oriented example would be a file in a directory, as every file has a name, a size and a date of when it was created.

As you can see in the image above, when we use the type function as we just did here, Python tells us which class the value or variable belongs to. And since integers and strings are classes, they have a bunch of attributes and methods associated with them. You can access attributes and methods of a class with the dir function in Python, as shown below:

In my previous article about strings, I explored a bunch of methods and attributes of the string class. Take a look at it for further insights about how to treat strings objects, which in that case will be a different instance of the string class. This means that they all have the same methods, although the content in the string is different.

Why are there a bunch of methods that begin and end with double underscores?

These are called special methods and they aren’t usually called by those weird names. Instead, they’re called by some of the internal Python functions. for example, the __len__ method is called by the len function.

If you want to know what a specific method does, you should use the help function:

When we use the help function on any variable or value, we’re accessing all the documentation for the corresponding class. In this case, we’re looking at the documentation for the str and the int class.

Although Python comes with a lot of predefined classes for us, the power of object-oriented programming comes when we define our own classes with their own attributes and methods.

2. Defining a New Class

As mentioned earlier, the point of object oriented programming is to help define a real-world concept in a way that the computer understands. Let’s get hands on to build a new class with the car example:

Let’s clarify specific elements of the code:

In Python, we use the class reserved keyword to tell the computer that we’re starting a new class. We follow this with the name of the class and a colon. Python style guidelines recommend that class names should start with a capital letter . In my case, the class is called Car.

reserved keyword to tell the computer that we’re starting a new class. We follow this with the name of the class and a colon. Python style guidelines recommend that class names should start with a . In my case, the class is called Car. After the line with the class definition comes the body of the class, which is indented to the right, following the pattern of loops or functions.

We’ll get to the special methods init and repr in the fourth section of this article.

How might we expand our definition of the Car class? It would probably have the same attributes that represent the information we want to associate with a car like brand and color.

Now, let’s proceed with the creation of an instance of the class Car, and assign it to a variable called “my_car”. To create a new instance of any class, we call the name of the class as if it were a function:

As you can see, I’m passing as an argument the brand and the color as I’ve configured my class to require both items in the creation of a new object of the class. As a result, we can call the attributes of the created instance and receive the value previously assigned:

The syntax used to access the attributes is called dot notation because of the dot used in the expression. Dot notation lets you access any of the abilities that the object might have, such as brand or color.

The attributes and methods of some objects can be other objects and can have attributes and methods of their own. For example, we could use the upper or the capitalize methods to modify both string attributes of my instance:

So far we’ve created one instance of the Car class and set its attributes. Now, we could create a new instance of the the class with different attributes:

3. Instance Methods

Methods are essentially called to make objects do stuff. For example, upper and capitalize for strings. The key to learn the intuition of methods in O.O.P. is to understand that methods are functions that operate on the attributes of a specific instance of a class. When we call the lower method on the string, we’re making the contents of that specific string lowercase.

Let’s take a closer look by creating a new class called Dog and defining our own methods. First, we need to define the class and create an instance of it like we’ve done before with the Car class. While my dog might be great, it can’t perform any actions as long as I don’t define methods for them. Take a look at the example:

As shown in the image, we must start defining a method with the def keyword just like we would for a function, and indent to the right the body of the method, also as we would for a function.

The function is receiving a parameter called “self”. This parameter represents the instance that the method is being executed on.

Even though my dog barks, it will always do it in the same way. We can change how it will bark with a simple modification in the code, in order to gain flexibility in the attributes and methods that we configure to our classes:

4. Defining Constructors and Other Special Methods

Both classes created up to this paragraph contain default values as attributes and methods. This is not an ideal scenario as it creates redundant code for each attribute, and more importantly, as it makes it really easy to forget to set an important value.

So, when writing code it's a good idea to set attributes and methods that will vary with instances upon creating the class, in order to make sure that each instance contains the same important attributes. To do this, we need to use a special method called Constructor.

The constructor of the class is the method that's called when you call the name of the class. It's always named init.

It contains the keyword self, which refers to the instance being created, and the arguments that will be passed as attributes by the programmer once the instance is created, like we do in the example below:

The second method of the class is the repr method, which tells Python to print a predetermined statement every time an instance of the class is called, as in the image above.

Want to know which is a specific method’s function? Refer to the help function introduced previously. As built-in classes include a guide to help users understand the intuition behind each method or attribute, we could also do this on our own classes, methods, and functions. We can do that by adding a Docstring.

A Docstring is a brief text that explains what something does.

Once you include documentation to your classes and objects, you’ll get much more information about the methods created that will facilitate re-usability of the code and help other users to understand it. Remember that the docstring always has to be indented at the same level of the block it’s documenting.

5. Code Reuse

Another important aspect of object-oriented programming is Inheritance. Just like people have parents, grandparents, and so on, objects have an ancestry. The principle of inheritance lets a programmer build relationships between concepts and group them together. In particular, this allows us to reduce code duplication by generalizing our code.

For example, how can we define a representation of “other means of transport” apart from the car that we already created, or other pets apart from my dog. This grouping characteristic allows us to create other classes that share some of the attributes of the existing classes, but not all of them, in order to add other similar instances without rewriting existing code.

In Python, we use parentheses in the class declaration to show an inheritance relationship. In the transportation example above, I’ve used Python’s syntax to tell the computer that both the car and the train inherit from the MyTransports class. Because of this, they automatically have the same constructor, which sets the color and brand attributes.

With the inheritance technique, we can use the transportation class to store information that applies to all kinds of transports available, and keep car or train specific attributes in their own classes. You can think of the MyTransports class as the parent class, and the Car and Train classes as siblings.

An example that is closer to the tasks you would perform in an IT department would be a system that handles the employees at your company. You may have a class called employee, which could have the attributes for things like full name of the person, the username used in company systems, the groups the employee belongs to, and so on. The system could also have a manager class which also is an employee, but additional information associated with it, like the employees that report to a specific manager.