
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
8 Tips for Object Oriented Programming in Python
Object-oriented programming language is a programming paradigm that is widely used in software design as it makes the code reusable and reduces code redundancy. It uses classes and objects to implement real-world objects in programming. Python and other languages like C++, java, javascript, etc support object-oriented programming. In this article, we will understand the characteristics of object-oriented programming and some tips to use object-oriented programming in Python.
In object-oriented programming, objects are created from their class blueprint. These objects represent real-world objects as they have some properties called attributes and methods just like real-world objects have their own properties and behavior. For example, if we consider a Dog as a real-world object then it has certain properties like breed, color, size, and also some behaviors like barking, running speed, etc. These properties and behavior can be encapsulated in a Dog object which will have its attributes and methods to represent a dog in programming.
Object-oriented programming has 4 characteristics that can make the code more modular, reusable, and maintainable ?
Inheritance
In Inheritance, a new class is created from an already existing class i.e the new class uses the methods and behavior of the existing class which makes the code more reusable and maintainable. Inheritance gives the functionality to also add new functions to the new class and to override existing functions of the old class in the inherited class. Inheritance reduces code complexity and makes the code more reusable and scalable.
Encapsulation
Encapsulation is the process of encapsulating data and the functions using that data in a single entity. OOP encapsulates its data and the function that uses that data in class and allows access and modification to that data and functions in a controlled way. Encapsulation uses access modifiers like public, private, and protected to provide restricted access to the data and functions of a class.
Polymorphism
Objects behaving in different ways in different situations is done using polymorphism. In OOP, polymorphism can be achieved through method overloading and method overriding. Method overloading is the process of creating multiple methods with the same name but different parameters, while method overriding is the process of creating a new implementation of a method in a subclass. Polymorphism allows developers to write more flexible and adaptable code, making it easier to add new functionality or features to the system without breaking existing code.
Data Abstraction
Abstraction is the process of hiding the implementation details of the object and showing only the functionality. Due to abstraction the user is able to know what the function is doing but is unable to understand how it is working or the internal details of the function. Abstraction allows developers to create a high-level view of the system, making it easier to understand and manage the complexity of the code
Now, let's look at some tips for object-oriented programming in Python ?
Use Classes to Model any Real-world Object
Classes are the blueprints that define the attributes and methods of the object. Before creating an object make sure that it is created from a valid class as when we create an instance of a class we create an object with real values to its attributes.
Example
If you are creating a game first create classes for players, enemies, weapons, and items and then create instances of those classes to create the game logic.
class Player: def __init__(self, player_name): self.player_name = player_name class Enemy: def __init__(self, enemy_name, enemy_health): self.enemy_name = enemy_name self.enemy_health = enemy_health class Weapon: def __init__(self, weapon_name, weapon_damage): self.weapon_name = weapon_name self.weapon_damage = weapon_damage class Game: def __init__(self, players, enemies, weapons): self.players = players self.enemies = enemies self.weapons = weapons def start_game(self): print("Game has started") def end_game(self): print("Game has ended") # create some players, enemies, and weapons player1 = Player("John") player2 = Player("Jane") enemy1 = Enemy("Zombie", 50) enemy2 = Enemy("Goblin", 75) weapon1 = Weapon("Sword", 25) weapon2 = Weapon("Axe", 30) # create a game object with the players, enemies, and weapons game = Game([player1, player2], [enemy1, enemy2], [weapon1, weapon2]) # start the game game.start_game() # play the game... # end the game game.end_game()
Output
Game has started Game has ended
Use Meaningful Naming Convention
Use meaningful names for the classes and also the attributes and functions defined in the class. The name should specify the behavior of the class and the functions. In the industry, Camel-Casing is used as a default naming convention. Always make sure that the one class, attribute, and method is responsible for only one task.
Example
In the below example, a Person class is created with the class name "Person" and attributes such as name, age, and occupation.
class Person: def __init__(self, person_name, person_age,person_occupation): # type: (str, int, str) -> None self.person_name = person_name self.person_age = person_age self.person_occupation = person_occupation def introduce(self): # type: () -> str return "Myself {}, I am {} years old, and I work as a {}.".format(self.person_name, self.person_age, self.person_occupation) # Create a person object person1 = Person("John Smith", 35, "Software Engineer") # Call the introduce method to get the person's introduction introduction = person1.introduce() # Print the introduction print(introduction)
Output
Myself John Smith, I am 35 years old, and I work as a Software Engineer.
Differentiate Between Class and Instance-level Data
As inheritance is an important pillar of OOPs, it is necessary to differentiate between class-level and instance-level data to better understand inheritance. The attributes of the instance of a class are restricted to that object and these attributes are defined inside the constructor of the class whereas the attributes which belong specifically to the class are defined outside the constructor function of the class.
Example
In the below example, we created a class Car with class level attribute and instance level attribute. The class level attribute and instance level attribute can be accessed as follows ?
class Car: # class-level attribute category = 'Vehicle' def __init__(self, make, model): # instance-level attribute self.make = make self.model = model # creating instances of Car class car1 = Car('Toyota', 'Corolla') car2 = Car('Honda', 'Civic') # accessing class-level attribute print(Car.category) # output: Vehicle # accessing instance-level attributes print(car1.make, car1.model) # output: Toyota Corolla print(car2.make, car2.model) # output: Honda Civic # changing class-level attribute value Car.category = 'Automobile' # accessing updated class-level attribute print(Car.category) # output: Automobile # changing instance-level attribute value car1.make = 'Nissan' # accessing updated instance-level attribute print(car1.make, car1.model) # output: Nissan Corolla
Output
Vehicle Toyota Corolla Honda Civic Automobile Nissan Corolla
Use Polymorphism to Write Flexible Code
polymorphism is the process by which functions or objects can be used in different forms. Using polymorphism you can write flexible code by which objects from different classes can be used interchangeably with the same function which reduces the code and avoids redundancy. For example, if you have a function that takes a list of objects as an argument, you can pass in a list of any objects that have the same interface. This allows you to write generic code that can work with a variety of objects.
Docstring in Python
For a better understanding of the code developers use to write comments in the code so that the other person reading it can easily understand what the function is doing. But this is not a convenient way for large Python packages, modules, and functions. So Python structured document also called docstring provides a convenient way to document the public Python packages, functions, and methods to describe what the function does. You can use ?''' triple single quote''' or """ triple-double quote""" to write docstring in Python.
Example
In the below example, we created a function calculate_area for calculating the area of the rectangle given its length and width. The doc string is enclosed in triple quotes which describe the function, the parameters of the function, and the return type of the function.
def calc_area(len, wid): """ Given the length and width of the rectangle , calculate its area. Parameters: len (float): The length of the rectangle. wid (float): The width of the rectangle. Returns: Float: Reactangle calculated area. """ area = length * width return area
We can access the docstring using help function as follows ?
print(help(calculate_area)) print(calculate_area.__doc__)
Output
Help on function calc_area in module __main__: calc_area(len, wid) Given the length and width of the rectangle , calculate its area. Parameters: len (float): The length of the rectangle. wid (float): The width of the rectangle. Returns: Float: Reactangle calculated area. None Given the length and width of the rectangle , calculate its area. Parameters: len (float): The length of the rectangle. wid (float): The width of the rectangle. Returns: Float: Reactangle calculated area.
Setting Access to Attributes
Attributes are properties of the object defined inside the class and are used by the object to get, set, or update values to it and the methods associated with them. Python provides some inbuilt functions to access and manipulate the attributes of the class.
getattr() ? This function is used to get or access the value of the attribute .
setattr() ? This function is used to update the value of the attribute.
hasattr() ? This function is used to check if the attribute exists or not.
delattr() ? This function is used to delete an attribute.
Example
In the below example, we set the access for the class Car attributes using getter and setter functions as follows ?
class Car: def __init__(self, car_company, car_model): self.car_company = car_company self.car_model = car_model car1 = Car('Toyota', 'Corolla') # setting attribute value using setattr setattr(car1, 'color', 'red') # getting attribute value using getattr print(getattr(car1, 'car_company')) # output: Toyota # checking attribute existence using hasattr print(hasattr(car1, 'car_model')) # output: True print(hasattr(car1, 'year')) # output: False # deleting attribute using delattr delattr(car1, 'color') print(hasattr(car1, 'color')) # output: False
Output
Toyota True False False
Use Abstract Classes
Abstract class provides a common interface for the implementation of a component. The methods created in abstract classes can be used in any child class created from the abstract class. Abstract class reduces the code for the developer and makes the code more maintainable.
Example
In the below example we create an abstract class called Animal with the method make_sound and all other classes that inherit from it should implement the make_sound method.
try: from abc import ABC, abstractmethod except ImportError: # Python 2.x fallback class ABCMeta(type): def __new__(cls, name, bases, namespace): return type.__new__(cls, name, bases, dict(namespace)) class ABC(object): __metaclass__ = ABCMeta def abstractmethod(method): method.__isabstractmethod__ = True return method class Animal(ABC): @abstractmethod def make_sound(self): pass class Cat(Animal): def make_sound(self): print("Meow") class Dog(Animal): def make_sound(self): print("Woof") # creating objects cat = Cat() dog = Dog() # calling methods cat.make_sound() # output: Meow dog.make_sound() # output: Woof
Output
Meow Woof
Pep8 Guidelines
In 2001 Guido van Rossum, Barry Warsaw, and Nick Coghlan created some coding conventions which must be taken care of while creating Python packages. These coding conventions are called Python Enterprise proposal or PEP guidelines. Apart from code quality, other factors should also be taken care of while creating Python packages. All these factors are mentioned in the PEP guidelines. Some of the important factors are ?
Each line of code should be limited to 80 characters
Import all libraries required in the beginning of the code.
Do not use redundant variables inside the code.
Example
In the below example, we created a calculate_area method in two different ways. The good example is implemented using pep8 guidelines while the Bad example does not follow the pep8 guidelines.
# Good Example def calc_area(wid, ht): """Calculate the area of a rectangle.""" calculated_area = wid * ht return calculated_area # Bad Example def Calc_Area(Wid, Ht): calculated_area=Wid*Ht return calculated_area # PEP 8 naming conventions print(calc_area.__name__) print(Calc_Area.__name__)
Output
calc_area Calc_Area
Conclusion
In this article, we discussed various tips for object-oriented programming with suitable examples. By following the tips we discussed in this article we can write object-oriented code that is well-organized, modular, and easy to maintain.