Object-oriented Programming (OOP)
Tags: python, beginners, programming, tutorial
Published: 2023-04-27 21:14:15

Object-oriented programming (OOP) is a programming paradigm that focuses on the use of objects to represent and manipulate data. Python is an object-oriented language, which means that it supports the creation and manipulation of objects. In this blog post, we will explore the basic concepts of OOP in Python, including classes, objects, inheritance, encapsulation, and polymorphism.
## Classes and Objects
In Python, a class is defined using the `class` keyword, followed by the name of the class and a colon. The properties and methods of the class are defined within the class body using the `def` keyword.

For example, the following code snippet defines a class called `Person` that has two properties (`name` and `age`) and a method (`introduce`) that prints a message introducing the person:

```
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def introduce(self):
        print("Hi, my name is", self.name, "and I am", self.age, "years old.")

person1 = Person("Alice", 25)
person2 = Person("Bob", 30)

person1.introduce()
person2.introduce()
```

Output:

```
Hi, my name is Alice and I am 25 years old.
Hi, my name is Bob and I am 30 years old.
```
## Inheritance
In Python, inheritance is achieved by creating a subclass that inherits the properties and methods of its parent class. To create a subclass, the `class` keyword is used followed by the name of the subclass and the name of the parent class in parentheses.

For example, the following code snippet defines a parent class called `Animal` that has a property (`species`) and a method (`make_sound`). The code also defines a child class called `Dog` that inherits from `Animal` and adds a new method (`bark`):

```
class Animal:
    def __init__(self, species):
        self.species = species
        
    def make_sound(self):
        pass

class Dog(Animal):
    def bark(self):
        print("Woof!")

dog = Dog("Canine")
print(dog.species)
dog.bark()
```

Output:

```
Canine
Woof!
```
## Encapsulation
In Python, encapsulation is achieved using naming conventions. Properties and methods that are intended to be private are prefixed with a double underscore (`__`), while properties and methods that are intended to be protected are prefixed with a single underscore (`_`).

For example, the following code snippet defines a class called `BankAccount` that has a private property (`__balance`) and two public methods (`deposit` and `withdraw`):

```
class BankAccount:
    def __init__(self, initial_balance):
        self.__balance = initial_balance
        
    def deposit(self, amount):
        self.__balance += amount
        
    def withdraw(self, amount):
        if amount <= self.__balance:
            self.__balance -= amount
        else:
            print("Insufficient balance")
            
    def get_balance(self):
        return self.__balance

account = BankAccount(1000)
account.deposit(500)
account.withdraw(2000)
print(account.get_balance())
```

Output:

```
Insufficient balance
1500
```
## Polymorphism
In Python, polymorphism is achieved through the use of duck typing. Duck typing is a programming concept that allows objects of different types to be treated as if they were the same type as long as they implement the same methods.

For example, the following code snippet defines two classes (`Rectangle` and `Triangle`) that have a common method (`calculate_area`). Even though the classes have different implementations, they can both be passed as arguments to a function (`print_area`) that expects an object with a `calculate_area` method:

```
class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width
        
    def calculate_area(self):
        return self.length * self.width

class Triangle:
    def __init__(self, base, height):
        self.base = base
        self.height = height
        
    def calculate_area(self):
        return 0.5 * self.base * self.height

def print_area(shape):
    area = shape.calculate_area()
    print("The area is", area)

rectangle = Rectangle(5, 3)
triangle = Triangle(4, 6)

print_area(rectangle)
print_area(triangle)
```

Output:

```
The area is 15
The area is 12.0
```

We have learned about classes and objects, inheritance, encapsulation, and polymorphism. By mastering these concepts, you can write more efficient, flexible, and reusable code that can be easily maintained and extended.