Object Oriented Programming in Python

Create interesting classes and place objects in them!

Object-Oriented Programming in Python

Object-Oriented Programming (OOP) is a programming paradigm that uses objects to structure code. Python is a multi-paradigm language that fully supports object-oriented programming.

1. Classes and Objects

Classes are blueprints for creating objects:

# Basic class definition
class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def bark(self):
        return f"{self.name} says Woof!"

# Creating objects
my_dog = Dog("Rex", 3)
print(my_dog.name)    # "Rex"
print(my_dog.bark())  # "Rex says Woof!"

2. Inheritance with Abstract Methods

Inheritance allows classes to inherit attributes and methods from other classes. Abstract methods are methods that must be implemented by subclasses.

from abc import ABC, abstractmethod

# Parent class with an abstract method
class Animal(ABC):
    def __init__(self, name):
        self.name = name
    
    @abstractmethod
    def speak(self):
        pass

# Child classes
class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"

# Using inherited classes
dog = Dog("Rex")
cat = Cat("Whiskers")
print(dog.speak())    # "Rex says Woof!"
print(cat.speak())    # "Whiskers says Meow!"

3. Encapsulation

Encapsulation is the bundling of data and methods that work on that data within a single unit:

class BankAccount:
    def __init__(self):
        self.__balance = 0  # Private attribute
    
    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return True
        return False
    
    def get_balance(self):
        return self.__balance

# Using encapsulation
account = BankAccount()
account.deposit(100)
print(account.get_balance())  # 100
# print(account.__balance)    # This would raise an error

4. Polymorphism

Polymorphism allows us to use a single interface with different underlying forms (data types or classes):

# Polymorphic function
def make_speak(animal):
    return animal.speak()

# Different classes with same interface
class Dog:
    def speak(self):
        return "Woof!"

class Cat:
    def speak(self):
        return "Meow!"

class Duck:
    def speak(self):
        return "Quack!"

# Using polymorphism
animals = [Dog(), Cat(), Duck()]
for animal in animals:
    print(make_speak(animal))

5. Properties and Decorators

Properties allow you to create managed attributes:

class Person:
    def __init__(self, name):
        self._name = name
    
    @property
    def name(self):
        return self._name
    
    @name.setter
    def name(self, value):
        if not isinstance(value, str):
            raise ValueError("Name must be a string")
        self._name = value
    
# Using properties
person = Person("Alice")
print(person.name)     # "Alice"
person.name = "Bob"    # This works
# person.name = 123    # This would raise an error

6. Class and Static Methods

Special methods that work with classes:

class MathOperations:
    @staticmethod
    def add(x, y):
        return x + y
    
    @classmethod
    def multiply(cls, x, y):
        return x * y
    
    def divide(self, x, y):
        return x / y

# Using different types of methods
print(MathOperations.add(5, 3))      # Static method
print(MathOperations.multiply(4, 2))  # Class method
math_ops = MathOperations()
print(math_ops.divide(10, 2))        # Instance method

7. Magic Methods

Special methods that customize class behavior:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __str__(self):
        return f"Point({self.x}, {self.y})"
    
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)
    
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

# Using magic methods
p1 = Point(1, 2)
p2 = Point(3, 4)
print(p1)          # "Point(1, 2)"
print(p1 + p2)     # "Point(4, 6)"
print(p1 == p2)    # False

Conclusion

Object-Oriented Programming (OOP) in Python uses classes and objects to organize code, promoting reusability and organization. By defining classes, developers can create object blueprints with shared attributes and behaviors, simplifying code maintenance and improving project scalability. Inheritance allows classes to inherit attributes and methods from others, with abstract methods that subclasses must implement. Encapsulation bundles data and methods in one unit, while polymorphism enables a single interface with different forms. Properties, decorators, class methods, and static methods are key in OOP, along with magic methods that customize class behavior.