What is Object-Oriented Programming?
Python is an object-oriented programming language. Object-oriented programming is a programming paradigm that structures programs such that data and functions are bundled into individual objects. For instance, an object could represent a car with data like a type, color, and model and functions such as driving, parked, neutral, and reversing. Objects are at the center of object-oriented programming in Python, not only representing the data but in the overall structure of the program as well.
Object-Oriented Programming concepts
In this article, we will be discussing the following OOP concepts:
- Class and Objects
- Inheritance
- Overriding parent method
- Encapsulation
- Polymorphism
Classes and Objects
An object is an entity that has data(variables) and functions(methods) associated with it. A class is like an object constructor or a "blueprint" for creating objects. The class defines attributes and the behavior of the object, while the object, on the other hand, represents the class.
Confusing right? don't worry you will understand better with a few examples.
But first, let us look at some inbuilt classes in python:
C:\Users\ODION>python
Python 3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> num = 5
>>> type(num)
<class 'int'>
>>> string = 'string'
>>> type(string)
<class 'str'>
>>> lst = []
>>> type(lst)
<class 'list'>
>>> tpl = ()
>>> type(tpl)
<class 'tuple'>
>>> sets = set()
>>> type(sets)
<class 'set'>
>>> dct = {}
>>> type(dct)
<class 'dict'>
>>> boolean = True
>>> type(boolean)
<class 'bool'>
Creating a Class
To create a class we need to use the keyword class
followed by the name and colon. The class name should be CamelCase
.
# syntax
class ClassName:
'''code goes here'''
Example:
class Person:
pass
print(Person)
Output:
<class '__main__.Person'>
Creating an Object
We can create an object by calling the class.
obj = Person()
print(obj)
Output:
<__main__.Person object at 0x000001FD94D7A680>
Here obj
is an object of the class Person
Class Constructor
In the examples above, we have created an object from the Person
class. However, a class without a constructor is not really useful in real applications. The properties that all Person objects must have are defined in a method called __init__()
. __init__()
initializes each new instance of the class. Let us use the constructor function to make our class more useful. The __init__()
constructor function has self
parameter which is a reference to the current instance of the class.
Examples:
class Person:
def __init__ (self, name):
# self allows to attach parameter to the class
self.name =name
p = Person('Odion')
print(p.name)
print(p)
Output:
Odion
<__main__.Person object at 0x2abf46907e80>
Let us add more parameters to the constructor function.
class Person:
def __init__(self, firstname, lastname, age, country, city):
self.firstname = firstname
self.lastname = lastname
self.age = age
self.country = country
self.city = city
p = Person('Odion', 'Sonny', 200, 'Nigeria', 'Lagos')
print(p.firstname)
print(p.lastname)
print(p.age)
print(p.country)
print(p.city)
Output:
Odion
Sonny
200
Nigeria
Lagos
Object Methods
Objects can have methods. The methods are functions that belong to the object and are defined inside a class.
Example:
class Person:
def __init__(self, firstname, lastname, age, country, city):
self.firstname = firstname
self.lastname = lastname
self.age = age
self.country = country
self.city = city
def person_info(self):
return f'{self.firstname} {self.lastname} is {self.age} years old. He lives in {self.city}, {self.country}'
p = Person('Odion', 'Sonny', 200, 'Nigeria', 'Lagos')
print(p.person_info())
Output:
Odion Sonny is 200 years old. He lives in Lagos, Nigeria
Object Default Methods
Just like when writing functions in python, sometimes you may assign default values for your object methods. By giving default values to the parameters in the constructor, we can avoid errors when we call or instantiate our class without parameters. Let's see how it looks:
Example:
class Person:
def __init__(self, firstname='Odion', lastname='Sonny', age=200, country='Nigeria', city='Lagos'):
self.firstname = firstname
self.lastname = lastname
self.age = age
self.country = country
self.city = city
def person_info(self):
return f'{self.firstname} {self.lastname} is {self.age} years old. He lives in {self.city}, {self.country}.'
p1 = Person()
print(p1.person_info())
p2 = Person('John', 'Doe', 60, 'Ghana', 'Accra')
print(p2.person_info())
Output:
Odion Sonny is 200 years old. He lives in Lagos, Nigeria.
John Doe is 60 years old. He lives in Accra, Ghana.
Method to Modify Class Default Values
In the example below, the Person
class, all the constructor parameters have default values. In addition, we have hobbies
parameter, which we can access using a method. Let us create add_hobbies
method to add hobbies to the hobbies list.
class Person:
def __init__(self, firstname='Odion', lastname='Sonny', age=200, country='Nigeria', city='Lagos':
self.firstname = firstname
self.lastname = lastname
self.age = age
self.country = country
self.city = city
self.hobbies= []
def person_info(self):
return f'{self.firstname} {self.lastname} is {self.age} years old. He lives in {self.city}, {self.country}.'
def add_hobbies(self, hobbies):
self.hobbies.append(hobbies)
p1 = Person()
print(p1.person_info())
p1.add_hobbies('Swimming')
p1.add_hobbies('Basket ball')
p1.add_hobbies('Programming')
p2 = Person('John', 'Doe', 60, 'Ghana', 'Accra')
print(p2.person_info())
print(p1.hobbies)
print(p2.hobbies)
Output:
Odion Sonny is 200 years old. He lives in Lagos, Nigeria.
John Doe is 60 years old. He lives in Accra, Ghana.
['Swimming', 'Basket ball', 'Programming']
[]
Inheritance
Using inheritance we can reuse parent class code. Inheritance allows us to define a class that inherits all the methods and properties from the parent class. The parent class or super or base class is the class that gives all the methods and properties. The child class is the class that inherits from another or parent class.
Let us create a student class by inheriting from person
class.
class Student(Person):
pass
s1 = Student('Temilade' 'Openiyi' 27, 'Nigeria', 'Lagos')
s2 = Student('Ayodeji', 'Balogun', 31, 'Nigeria', 'Lagos')
print(s1.person_info())
s1.add_hobbies('Shopping')
s1.add_hobbies('Dancing')
s1.add_hobbies('Singing')
print(s1.hobbies)
print(s2.person_info())
s2.add_hobbies('Jogging')
s2.add_hobbies('Drawing')
s2.add_hobbies('Skiing')
print(s2.hobbies)
Output:
Temilade Openiyi is 27 years old. He lives in Lagos, Nigeria.
['Shopping', 'Dancing', 'Singing']
Ayodeji Balogun is 31 years old. He lives in Lagos, Nigeria.
['Jogging', 'Drawing', 'Skiing']
We did not call the __init__()
constructor in the child class. If we didn't call it then we can still access all the properties from the parent. But if we do call the constructor we can access the parent properties by calling super()
.
We can add a new method to the child or we can override the parent class methods by creating the same method name in the child class. When we add the __init__()
function, the child class will no longer inherit the parent's __init__()
function.
Overriding parent method
class Student(Person):
def __init__ (self, firstname='Odion', lastname='Sonny' ,age=200, country='Nigeria', city='Lagos', gender='male'):
self.gender = gender
super().__init__(firstname, lastname, age, country, city)
def person_info(self):
gender = 'He' if self.gender == 'male' else 'She'
return f'{self.firstname} {self.lastname} is {self.age} years old. {gender} lives in {self.city}, {self.country}.'
s1 = Student('Temilade' 'Openiyi' 27, 'Nigeria', 'Lagos', 'female')
s2 = Student('Ayodeji', 'Balogun', 31, 'Nigeria', 'Lagos', 'male')
print(s1.person_info())
s1.add_hobbies('Shopping')
s1.add_hobbies('Dancing')
s1.add_hobbies('Singing')
print(s1.hobbies)
print(s2.person_info())
s2.add_hobbies('Jogging')
s2.add_hobbies('Drawing')
s2.add_hobbies('Skiing')
print(s2.hobbies)
Temilade Openiyi is 27 years old. She lives in Lagos, Nigeria.
['Shopping', 'Dancing', 'Singing']
Ayodeji Balogun is 31 years old. He lives in Lagos, Nigeria.
['Jogging', 'Drawing', 'Skiing']
We can use super()
built-in function or the parent name Person to automatically inherit the methods and properties from its parent. In the example above, the child method has a different feature, it can identify if the gender is male or female and assign the proper pronoun(He/She).
Encapsulation
In object-oriented programming, restricting access to methods and variables to prevent data from direct modification is known as Encapsulation. Let us look at a new class called Name
.
class Name:
def __init__(self):
self.__defaultname = "John Doe"
def displayName(self):
print(f"Your name is: {self.__defaultname}")
def resetName(self, newname):
self.__defaultname = newname
c = Name()
c.displayName()
# change the price
c.__defaultname = "Odion Sonny"
c.displayName()
# using setter function
c.resetName("Odion Sonny")
c.displayName()
Output
Your name is: John Doe
Your name is: John Doe
Your name is: Odion Sonny
In the above program, we defined a Name
class.
We used __init__()
method to store the default name of Name
. Here, notice the code.
c.__defaultname = Odion Sonny
Here, we have tried to modify the value of __defaultname
outside of the class. However, since __defaultname
is a private variable, this modification is not seen on the output.
As shown, to change the value, we have to use a setter function i.e resetName()
which takes price as a parameter.
Polymorphism
Polymorphism is simply the ability of an object to have many forms. it allows us to perform the same action in many different ways. For example, the Python built-in function len()
can be used to return the length of the items in a list or the length of the characters of a string.
Example
list1 = ['Hello', 'World']
string1= 'Hello world'
# calculate count
print(len(list1))
print(len(string1))
Output
2
11
Polymorphism with Inheritance
In Python, Polymorphism lets us define methods in the child class that have the same name as the methods in the parent class. In inheritance, the child class inherits the methods from the parent class. However, it is possible to modify a method in a child class that it has inherited from the parent class. This is particularly useful in cases where the method inherited from the parent class doesn’t quite fit the child class. In such cases, we re-implement the method in the child class. This process of re-implementing a method in the child class is known as Method Overriding.
Example
class Artiste:
def intro(self):
print("There are many music genres.")
def genre(self):
print("Different artistes have their main genre.")
class Beyonce(Artiste):
def genre(self):
print("Beyonce's main music genre is R&B/Soul.")
class Tems(Artiste):
def genre(self):
print("Tems' main music genre is Afrobeats.")
obj_art = Artiste()
obj_bey = Beyonce()
obj_tem = Tems()
obj_art.intro()
obj_art.genre()
obj_bey.intro()
obj_bey.genre()
obj_tem.intro()
obj_tem.genre()
Output
There are many music genres.
Different artistes have their main genre
Beyonce's main music genre is R&B/Soul.
Sparrows can fly.
Tems' main music genre is Afrobeats.
Ostriches cannot fly.
And that brings us to the end of this article!
Key Points to Remember:
- Object-Oriented Programming makes the program easy to understand as well as efficient.
- Since the class is sharable, the code can be reused.
- Data is safe and secure with data abstraction.
- Polymorphism allows the same interface for different objects, so programmers can write efficient code.
NB: Please write comments if you find anything incorrect, or if you want to share more information about the topic discussed above.