Object-oriented programming in Python is a powerful way to write clean, modular, and reusable code. Understanding Object Oriented Programming (OOP) is often considered difficult for beginners, However, I will try to make it as easy as possible so that you guys become pro in OOP. This article is a part of Python Learning Tutorial Series. By mastering the concepts of classes, encapsulation, inheritance, polymorphism, and abstraction, you can create systems that are efficient and easy to maintain.
Why Learn OOP?
OOP is a programming pattern that organizes code around objects rather than functions. Objects are instances of classes, which can be thought of as blueprints. We will learn more about classes and object later in this tutorial. Some on the important ways in which OOP helps is:
- Modularity: Code is easier to manage and debug.
- Reusability: Classes and objects can be reused in different programs.
- Scalability: Easily expand functionality without rewriting everything.
Key Concepts of OOP
OOP in Python revolves around four main concepts: Encapsulation, Inheritance, Abstraction, and Polymorphism. Encapsulation bundles data with methods, inheritance lets you create subclasses, abstraction hides complex details, and polymorphism allows for different implementations. Before we dive into 4 main concepts of OOP, we should first know what a class is and what object is
- Encapsulation
- Inheritance
- Polymorphism
- Abstraction
Classes and Objects
Think of a class as a structure/ skeleton/blueprint for creating something and objects as the final creation made from that structure. A class defines properties and behaviors, and an object is an actual usage of that class with the defined behaviour and properties.
Since this is a part of python learning series, we will see how actually a class is created in python? In Python, we define a class by using the class keyword followed by a name and a colon. Then we use .__init__() to declare which attributes each instance of the class should have:
class Dog: def __init__(self, name, breed): self.name = name self.breed = breed def bark(self): return f"Woof! I'm {self.name} the {self.breed}." # Creating objects (instances of the Dog class) my_dog = Dog("Buddy", "Golden Retriever") neighbor_dog = Dog("Max", "Beagle") print(my_dog.bark()) # Output: Woof! I'm Buddy the Golden Retriever. print(neighbor_dog.bark()) # Output: Woof! I'm Max the Beagle.
Here, Dog
is the class, and my_dog
and neighbor_dog
are objects.
Encapsulation
Encapsulation is like packing your belongings into a suitcase: it keeps data and methods safe from unauthorized access. In Python, this is achieved using private variables and methods.
class BankAccount: def __init__(self, account_holder, balance): self.account_holder = account_holder self.__balance = balance # Private variable def deposit(self, amount): self.__balance += amount def withdraw(self, amount): if amount > self.__balance: return "Insufficient funds." self.__balance -= amount return f"Withdrawn {amount}. Remaining balance: {self.__balance}" def get_balance(self): return self.__balance account = BankAccount("Alice", 1000) print(account.get_balance()) # Output: 1000 print(account.withdraw(200)) # Output: Withdrawn 200. Remaining balance: 800 # Trying to access the private variable directly will raise an AttributeError.
Encapsulation ensures data integrity by restricting direct access.
Inheritance
Inheritance allows a class to borrow properties and methods from another class. Think of it as a child inheriting traits from their parents.
class Animal: def __init__(self, species): self.species = species def make_sound(self): return "Some generic sound" class Cat(Animal): def __init__(self, name): super().__init__("Cat") # Call parent class constructor self.name = name def make_sound(self): return "Meow!" kitty = Cat("Whiskers") print(kitty.species) # Output: Cat print(kitty.make_sound()) # Output: Meow!
Here, the Cat
class inherits from the Animal
class, but it can also override its methods.
Polymorphism
Polymorphism means “many forms.” It allows different objects to use the same interface while behaving differently.
class Bird: def fly(self): return "I can fly." class Penguin(Bird): def fly(self): return "I can’t fly, but I can swim!" # Function that demonstrates polymorphism def describe_flight(bird): print(bird.fly()) sparrow = Bird() penguin = Penguin() describe_flight(sparrow) # Output: I can fly. describe_flight(penguin) # Output: I can’t fly, but I can swim!
Polymorphism makes code more flexible and dynamic.
Abstraction
Abstraction hides the complexity of the implementation and shows only the essential features. Abstract classes and methods are created using the abc
module.
from abc import ABC, abstractmethod class Vehicle(ABC): @abstractmethod def start_engine(self): pass class Car(Vehicle): def start_engine(self): return "Car engine started." class Motorcycle(Vehicle): def start_engine(self): return "Motorcycle engine started." # vehicle = Vehicle() # This would raise an error car = Car() motorcycle = Motorcycle() print(car.start_engine()) # Output: Car engine started. print(motorcycle.start_engine()) # Output: Motorcycle engine started.
Abstraction ensures focus on essential functionalities while hiding unnecessary details.
Wrapping Up
Object-oriented programming in Python is a powerful way to write clean, modular, and reusable code. By mastering the concepts of classes, encapsulation, inheritance, polymorphism, and abstraction, you can create efficient and easy-to-maintain systems. You can read in detail about each topic by clicking the link above. Once you become comfortable with OOP concepts, its advised to learn about design patters in patterns.