Loading...

Go Back

Next page
Go Back Course Outline

Python Full Course


Object-Oriented Programming (OOP) in Python

Object-Oriented Programming (OOP) Explained

Object-Oriented Programming (OOP) is a programming paradigm that organizes software design around objects and classes. It emphasizes encapsulation, inheritance, polymorphism, and abstraction. Below, we’ll break down the concepts and provide code examples in Python.

1. Basic OOP Concepts

1.1 Classes and Objects

A class is a blueprint for creating objects. It defines the structure and behavior of objects. An object is an instance of a class.

                        class Dog:
                            # Class attribute (shared by all instances)
                            species = "Canis familiaris"
                        
                            # Instance attributes (unique to each instance)
                            def __init__(self, name, age):
                                self.name = name
                                self.age = age
                        
                        # Creating objects (instances of the class)
                        dog1 = Dog("Buddy", 5)
                        dog2 = Dog("Max", 3)
                        
                        print(dog1.name)  # Output: Buddy
                        print(dog2.age)   # Output: 3
                        print(dog1.species)  # Output: Canis familiaris
                        
Output:
Buddy
3
Canis familiaris

1.2 Attributes and Methods

Attributes are variables that belong to an object or class. Methods are functions that belong to an object or class.

                        class Dog:
                            def __init__(self, name, age):
                                self.name = name
                                self.age = age
                        
                            # Method
                            def bark(self):
                                return f"{self.name} says woof!"
                        
                        dog1 = Dog("Buddy", 5)
                        print(dog1.bark())  # Output: Buddy says woof!
                        
Output:
Buddy says woof!


1.3 Encapsulation

Encapsulation is the bundling of data (attributes) and methods that operate on the data into a single unit (class). It also restricts direct access to some of an object's components, which is achieved using private attributes (e.g., _ or __ prefix in Python).

                        class BankAccount:
                            def __init__(self, balance):
                                self.__balance = balance  # Private attribute
                        
                            def deposit(self, amount):
                                self.__balance += amount
                        
                            def get_balance(self):
                                return self.__balance
                        
                        account = BankAccount(1000)
                        account.deposit(500)
                        print(account.get_balance())  # Output: 1500
                        # print(account.__balance)  # Error: AttributeError (private attribute)
                        
Output:
1500

1.4 Inheritance

Inheritance allows a class (child) to inherit attributes and methods from another class (parent). It promotes code reuse.

                        # Parent class
                        class Animal:
                            def __init__(self, name):
                                self.name = name
                        
                            def speak(self):
                                return "Sound"
                        
                        # Child class
                        class Dog(Animal):
                            def speak(self):
                                return f"{self.name} says woof!"
                        
                        dog = Dog("Buddy")
                        print(dog.speak())  # Output: Buddy says woof!
                        
Output:
Buddy says woof!

1.5 Polymorphism

Polymorphism allows objects of different classes to be treated as objects of a common superclass. It can be achieved through method overriding or duck typing.

                        class Cat(Animal):
                            def speak(self):
                                return f"{self.name} says meow!"
                        
                        animals = [Dog("Buddy"), Cat("Whiskers")]
                        for animal in animals:
                            print(animal.speak())
                        # Output:
                        # Buddy says woof!
                        # Whiskers says meow!
                        
Output:
Buddy says woof!
Whiskers says meow!

1.6 Constructors and Destructors

A constructor (__init__) initializes an object when it is created. A destructor (__del__) is called when an object is destroyed.

                        class Person:
                            def __init__(self, name):
                                self.name = name
                                print(f"{self.name} created.")
                        
                            def __del__(self):
                                print(f"{self.name} destroyed.")
                        
                        person = Person("Alice")
                        # Output: Alice created.
                        del person  # Output: Alice destroyed.
                        
Output:
Alice created.
Alice destroyed.

1.7 self Keyword

self refers to the current instance of the class. It is used to access attributes and methods of the object.

                        class Car:
                            def __init__(self, brand):
                                self.brand = brand
                        
                            def display(self):
                                print(f"This car is a {self.brand}.")
                        
                        car = Car("Toyota")
                        car.display()  # Output: This car is a Toyota.
                        
Output:
This car is a Toyota.

2. Advanced OOP Concepts

2.1 Class Methods and Static Methods

Class methods are bound to the class and not the instance. They use the @classmethod decorator and take cls as the first parameter. Static methods are utility methods that don't depend on the instance or class. They use the @staticmethod decorator.

                        class Math:
                            @classmethod
                            def add(cls, a, b):
                                return a + b
                        
                            @staticmethod
                            def multiply(a, b):
                                return a * b
                        
                        print(Math.add(2, 3))        # Output: 5
                        print(Math.multiply(2, 3))   # Output: 6
                        
Output:
5
6


2.2 Inheritance (Single and Multiple)

Single inheritance: A class inherits from one parent class. Multiple inheritance: A class inherits from multiple parent classes.

                        # Single inheritance
                        class Bird(Animal):
                            def speak(self):
                                return f"{self.name} says chirp!"
                        
                        # Multiple inheritance
                        class Bat(Animal, Bird):
                            pass
                        
                        bat = Bat("Batty")
                        print(bat.speak())  # Output: Batty says chirp!
                        
Output:
Batty says chirp!

2.3 Method Overriding and super()

Method overriding allows a child class to provide a specific implementation of a method already defined in the parent class. super() is used to call a method from the parent class.

                        class Animal:
                            def speak(self):
                                return "Sound"
                        
                        class Dog(Animal):
                            def speak(self):
                                return super().speak() + " but specifically woof!"
                        
                        dog = Dog()
                        print(dog.speak())  # Output: Sound but specifically woof!
                        
Output:
Sound but specifically woof!

2.4 Abstract Classes and Interfaces

Abstract classes cannot be instantiated and often contain one or more abstract methods (methods without implementation). Interfaces define a contract for classes (Python uses abstract classes for this purpose).

                        from abc import ABC, abstractmethod
                        
                        # Abstract class
                        class Shape(ABC):
                            @abstractmethod
                            def area(self):
                                pass
                        
                        class Circle(Shape):
                            def __init__(self, radius):
                                self.radius = radius
                        
                            def area(self):
                                return 3.14 * self.radius ** 2
                        
                        circle = Circle(5)
                        print(circle.area())  # Output: 78.5
                        
Output:
78.5

2.5 Data Hiding

Data hiding restricts access to certain attributes or methods using private variables (__ prefix).

                        class Secret:
                            def __init__(self, secret):
                                self.__secret = secret
                        
                            def reveal(self):
                                return self.__secret
                        
                        s = Secret("Confidential")
                        # print(s.__secret)  # Error: AttributeError
                        print(s.reveal())  # Output: Confidential
                        
Output:
Confidential

2.6 Property Decorators

Property decorators (@property, @<attribute>.setter, @<attribute>.deleter) allow controlled access to attributes.

                        class Temperature:
                            def __init__(self, celsius):
                                self._celsius = celsius
                        
                            @property
                            def celsius(self):
                                return self._celsius
                        
                            @celsius.setter
                            def celsius(self, value):
                                if value < -273.15:
                                    raise ValueError("Temperature below absolute zero is not possible.")
                                self._celsius = value
                        
                        temp = Temperature(25)
                        print(temp.celsius)  # Output: 25
                        temp.celsius = 30
                        print(temp.celsius)  # Output: 30
                        
Output:
25
30
Go Back

Next page