A Comprehensive Guide to Understanding Object-Oriented Programming (OOP) in Python
Exploring the Key Concepts of Object Oriented Programming in Python
In this article we'll cover in-depth about Object Oriented Programming (OOP) in Python programming. OOP concepts are pretty same for most programming languages but their syntax and implementation approach varies.
Brief information on OOP will be covered in this article, there are about 11 comprehensive and profound articles i published in my blog previously, were i explained OOP concepts extensively with profound examples in PHP, Dart and JavaScript.
Object Oriented Programming (OOP)
Object-oriented programming (OOP) is a programming style based on the idea of representing real life scenarios using "objects", with their unique or common description been represented as attributes and the set or defined way of their interaction or behavior referred to as methods.
Every standard attribute of object oriented programming languages are available in Python.
Class and Objects
A Class: a code template that is extensible to have more code templates inheriting it's member and behavior by providing their default or initial format of state(features or attributes) and actions(methods)
A car is a general name for a transport system with 4 tires which can be referred to as Car Class. Benz or Toyota is an object(example or instance) of this car class. Further more different models are instances or examples of Benz or Toyota which makes Toyota a class.
An Object: simply put, an object is an instance of a class. Objects themselves can become classes if instances are created from them. For example, the Toyota 4Runner can become an object of Toyota.
Python Class
- Structure of Class in Python
Class definition in Python starts with the reserved keyword class followed by the name of the class, then a colon before the body of the class.
class ClassName:
<statement | expression -1>
.
.
.
<statement | expression - N >
#(as much as the developer intends to write in the body of the code
NB: The pass keyword is used to skip the error that occurs when an empty class is defined because in Python class cannot be empty.
class Car:
pass
- Example of Class in Python
Attribute reference and instantiation are two operations are supported in Python. The value of a Class attribute can be altered by assigning a value to it depending on the access modifier definition.
class Car:
#docstring is also a valid class attribute
"""A Car class in Python"""
#class attribute brand
brand = "Earth"
# class function which in oop context is called method
def horn(self):
return 'method of car class'
In the example above, the name of the class is Car and it has attribute brand and method horn. This can be accessed by an instance (object) of the class with the dot . operator. The self parameter is similar to this in other programming language class definition. Any word can be used in place of self but it must be the first parameter. It basically points to the current instance of the class itself and can be used to access the attributes and methods. So what actually is Attribute and Method?
Attributes
Attributes are data members inside a class or an object that represent the different features of the class. They can also be referred to as characteristics of the class that can be accessed from other objects or differentiate a class from other classes. For example a car attribute include: tire, door, seats, license plate, headlight, wheel, handle, make, year, brand.
Methods
In classes methods are responsible to modify or define the behavior of the class and it's objects. A car method includes start, headLightOn, drive, stop, openDoor, horn etc. The methods in a class can either access(get or set) an attribute or perform a specific operation. It's a logic or procedure defined in a class to do something. Methods in classes lay out the behavior of objects that will be created. For instance, if a car owner presses the horn button it'll function by horning.
__str__() method
class Car:
"""A Car class in Python"""
def __init__(self, brand, location):
self.brand = brand
self.location = location
car1 = Car("Toyota", "Earth")
print(car1)
#<__main__.Car object at 0x000001781A752B90>
Without the __str__ function the class returns the object string. But when it is defined in the class it returns the string or response.
class Car:
"""A Car class in Python"""
def __init__(self, brand, location):
self.brand = brand
self.location = location
def __str__(self):
return f"My car name is: {self.brand} and the location is: {self.location}"
car1 = Car("Toyota", "Earth")
print(car1)
#My car name is: Toyota and the location is: Earth
Objects in Python
An object like earlier mentioned is an instance of a class. For example, A Toyota(an object) is a combination of the attributes(members or variables), methods(behaviors or actions), style of arrangement in the class of Car.
To instantiate an object (copy of a class) from a class is like assigning a function to a variable.
class Car:
#docstring is also a valid class attribute
"""A Car class in Python"""
#class attribute brand
brand = "Earth"
# class function which in oop context is called method
def horn(self):
print(f"Accessing the attribute from the method named brand: {self.brand}")
toyota = Car()
print(toyota.brand)
toyota.horn()
#Earth
#Accessing the attribute from the method named brand: Earth
In this snippet above, the toyota is an instance (object) of the Car class.
toyota.brand is used to access the car class attribute.
toyota.horn() is used to access the car class method.
Delete Object Properties
Objects in Python can be deleted using the Python del keyword.
#delete property on an object
del toyota.brand
#delete objects
del toyota
NB: variables within a method are unique to each instance created and the class attributes (variables) can be shared by all the instances of the class.
class Car:
brand = 'Baja' # class attribute will be shared by all instances of the class
def __init__(self, product):
self.product = product # instance attribute unique to each instance of the class
car1 = Car('Toyota')
car2 = Car('Honda')
print(f"car1 brand is: {car1.brand} and car2 brand is: {car2.brand} and the instance attribute for {car1.product} is unique to {car2.product}")
#car1 brand is: Baja and car2 brand is: Baja and the instance attribute for Toyota is unique to Honda
Constructor in Python
When creating class there are certain attributes or methods that might be needed for the class to function as designed or efficiently. The method that is defined in a class using __init__ is an example of Python's constructor. It is automatically invoked and executed when an object is created from a class. It’s a unique member function in a class responsible for initializing the expected parameters or behavior of its objects upon creation (instantiation). It is unique because it can take the name of the class.
Types of Constructor: Default constructor, Parameterized constructor, Copy constructor, Overloaded constructor
Note: constructors are optional in a class and some object oriented languages can automatically create one for you when there is none.
- Example of Python __init__ method (constructor)
Once the car1 object is instantiated the __init__ method gets invoked automatically.
class Car:
"""A Car class in Python"""
def __init__(self, brand, location):
self.brand = brand
self.location = location
car1 = Car("Toyota", "Earth")
print(f"My car name is: {car1.brand} and the location is: {car1.location}")
#My car name is: Toyota and the location is: Earth
Inheritance in Python
Inheritance is the mechanism in which a class inherit the attributes and methods of another class. The class which inherits from the other class is referred to as child class while the class whose methods and attributes were inherited is known as base class or parent class.
As the inheritance grows it begins to take a tree structure. The further it grows the deeper the tree structure. Hence the need for dependency injection.
Types of Inheritance: Single Inheritance, Multiple Inheritance, Multi-Level Inheritance.
- Structure of Inheritance in Python
class DerivedClassName(BaseClassName):
<statement | expression -1>
.
.
.
<statement | expression - N >
#(as much as the developer intends to write in the body of the code
- Python supports multiple inheritance
class DerivedClassName(BaseClassName1, BaseClassName2, BaseClassName3):
derived class is called child class while base class is called parent class.
- Example of Inheritance
# Base (parent) class
class Car:
def __init__(self, brand, year, price):
self.brand = brand
self.year = year
self.price = price
def details(self):
print(self.brand, self.year, self.price)
# Derived (Child) class Mercedes
class Mercedes(Car):
def horn(self, status):
print(f'The {self.brand} horn status is: {status}')
car = Mercedes('Mercedes-Benz G-Class', 'Dark Ash', 100000)
car.details()
car.horn(True)
car.horn(False)
The derived class can access the brand attribute and horn method of the parent class.
BaseClassName must to be defined in a namespace that is reachable from the scope that has the definition of the derived class. If the base class in defined in another module it can be accessed as shown below.
class DerivedClassName(modulename.BaseClassName):
Namespace
Namespace is the approach of grouping named scope to avoid conflicts with similar names as used in other scopes. Namespace block contains symbols that are grouped into a named scope to avoid conflicts with similarly named symbols in other scopes.
This is the meaning across several object-oriented languages but the implementation varies based on the syntax used.
According to Python documentation: A namespace is a mapping from names to objects. The important thing to know about namespaces is that there is absolutely no relation between names in different namespaces; for instance, two different modules may both define a function maximize
without confusion — users of the modules must prefix it with the module name.
Encapsulation in Python
Encapsulation is used to hide sensitive part of a method or class to avoid unwanted access or modification. Data hiding is controlled using getter or setter methods for data attributes that can allow read or write access by other classes.
A getter method is used to read the value of a specific data attributes within a class. A setter method is used to write or modify the value of a specific data attribute within a class.
Access modifiers(specifiers) are keywords or terms that defines the accessibility of classes, methods, and attributes. Access modifiers varies according to the syntax used by OOP languages to enhance the security or coverage of data members and methods.
Object Oriented Programming(OOP) Series: Access modifiers (public, private, protected) are used to define the way this hidden data is to be accessed.
In python, _attrName or __attrName is used to denote private attributes.
class Car:
"""A Car class in Python"""
def __init__(self, brand, location):
self.brand = brand
self.location = location
self.__config_rate = 5
def __str__(self):
return f"My car name is: {self.brand} and the location is: {self.location} with config rate of: {self.__config_rate}"
def setConfigRate(self, rate):
self.__config_rate = rate
car1 = Car("Toyota", "Earth")
print(car1)
car1.__config_rate = 10
print(car1)
# using the setter method to change the config rate
car1.setConfigRate(8)
print(car1)
The value of the __config_rate can only be changed using the setter method setConfigRate().
Polymorphism in Python
Polymorphic system (polymorphism) indicates the presence of an interface with multiple variations existing in one or more stages or forms of it's trait.
NB: Python supports method overriding (when same method name of the parent class is been used and modified in the child class) but does not support method overloading.
class Car:
def info(self):
pass
class Toyota(Car):
def info(self, brand):
print(f"This car brand is: {brand}")
class Mercedes(Car):
def info(self, brand):
print(f"This car brand is: {brand}")
car1 = Toyota()
car1.info("Toyota Corolla")
car2 = Mercedes()
car2.info("Mercedes-Benz G-Class")
The info method can perform different functionalities in different instances.
Data Abstraction in Python
An abstract class exposes functionality that are important for implementation. An abstract class is a class that cannot be instantiated directly except by a class that extends it to an object.
An abstract method is a method without implementation.
Abstract classes and interfaces in Python can be used to define data abstraction. An interface is an abstract class with defined methods but no implementations for the use of the methods.
Let's look at an example of an abstract class:
from abc import ABC, abstractmethod
class Car(ABC):
@abstractmethod
def info(self):
pass
@abstractmethod
def speed(self):
pass
class Toyota(Car):
def __init__(self, brand, location, color):
self.brand = brand
self.location = location
self.color = color
def info(self):
return f"My car name is: {self.brand} and the location is: {self.location}"
def speed(self):
return f"My car speed is 1000 with color: {self.color}"
car1 = Toyota('Mercedes-Benz G-Class', "Earth", "Dark Ash")
print(car1.info())
print(car1.speed())
#output
#My car name is: Mercedes-Benz G-Class and the location is: Earth
#My car speed is 1000 with color: Dark Ash
the ABC, abstractmethod is imported from abc module. The Car class has two abstract methods info() and speed() which got implemented by the Toyota subclass before the instance of the Toyota class is created.
Conclusion
In this article, we've covered in-depth on Object oriented programming (OOP). OOP is based on the idea of using "objects" to represent real-world scenarios. Each object's distinct or common description is represented by an attribute, and each method is a predetermined way for an object to interact or behave. OOP makes the code clean, structured, scalable and inheritable. Real life applications can be developed using the OOP approach. Python is an OOP language and can be used to develop applications that solve real-world problems. A class can be reused within or in other files as modules.
Find this helpful or resourceful?? kindly share and feel free to use the comment section for questions, answers, and contributions.