Object-Oriented Programming is a programming paradigm that organizes code into objects, which combine data (attributes) and behavior (methods). Python supports four main OOP principles:
Bundling data and methods that operate on that data within a single unit (class), and restricting direct access to some components.
class BankAccount:
def __init__(self, account_number, balance):
self.account_number = account_number # Public attribute
self.__balance = balance # Private attribute (name mangling with __)
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return f"Deposited ${amount}. New balance: ${self.__balance}"
return "Invalid amount"
def get_balance(self): # Getter method
return self.__balance
def __str__(self):
return f"Account {self.account_number}: ${self.__balance}"
# Usage
account = BankAccount("123456", 1000)
print(account.deposit(500)) # Deposited $500. New balance: $1500
print(account.get_balance()) # 1500
# print(account.__balance) # AttributeError - can't access private attribute directly
Creating new classes based on existing classes, inheriting their attributes and methods.
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
def make_sound(self):
return "Some generic sound"
def info(self):
return f"{self.name} is a {self.species}"
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, "Dog") # Call parent constructor
self.breed = breed
def make_sound(self): # Override parent method
return "Woof! Woof!"
def fetch(self):
return f"{self.name} is fetching the ball"
class Cat(Animal):
def __init__(self, name, color):
super().__init__(name, "Cat")
self.color = color
def make_sound(self):
return "Meow!"
# Usage
dog = Dog("Buddy", "Golden Retriever")
cat = Cat("Whiskers", "Orange")
print(dog.info()) # Buddy is a Dog
print(dog.make_sound()) # Woof! Woof!
print(cat.make_sound()) # Meow!
The ability of different classes to be treated as instances of the same class through a common interface.
class Shape:
def area(self):
pass
def perimeter(self):
pass
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14159 * self.radius ** 2
def perimeter(self):
return 2 * 3.14159 * self.radius
# Polymorphism in action
def print_shape_info(shape):
print(f"Area: {shape.area():.2f}")
print(f"Perimeter: {shape.perimeter():.2f}")
# Usage
rectangle = Rectangle(5, 3)
circle = Circle(4)
print("Rectangle:")
print_shape_info(rectangle) # Works with Rectangle
print("\nCircle:")
print_shape_info(circle) # Works with Circle
Hiding complex implementation details and showing only essential features of an object.
from abc import ABC, abstractmethod
class Vehicle(ABC): # Abstract base class
def __init__(self, brand, model):
self.brand = brand
self.model = model
@abstractmethod
def start_engine(self):
"""Must be implemented by subclasses"""
pass
@abstractmethod
def stop_engine(self):
"""Must be implemented by subclasses"""
pass
def display_info(self):
return f"{self.brand} {self.model}"
class Car(Vehicle):
def start_engine(self):
return f"{self.brand} car engine started with key"
def stop_engine(self):
return f"{self.brand} car engine stopped"
class ElectricCar(Vehicle):
def start_engine(self):
return f"{self.brand} electric motor activated silently"
def stop_engine(self):
return f"{self.brand} electric motor deactivated"
# Usage
# vehicle = Vehicle("Generic", "Model") # TypeError - can't instantiate abstract class
car = Car("Toyota", "Camry")
tesla = ElectricCar("Tesla", "Model 3")
print(car.start_engine()) # Toyota car engine started with key
print(tesla.start_engine()) # Tesla electric motor activated silently
Building complex objects by combining simpler ones (alternative to inheritance).
class Engine:
def __init__(self, horsepower):
self.horsepower = horsepower
def start(self):
return f"Engine with {self.horsepower}HP started"
class Wheels:
def __init__(self, count):
self.count = count
def rotate(self):
return f"{self.count} wheels rotating"
class Car:
def __init__(self, brand, engine, wheels):
self.brand = brand
self.engine = engine # Composition
self.wheels = wheels # Composition
def drive(self):
return f"{self.brand}: {self.engine.start()} and {self.wheels.rotate()}"
# Usage
engine = Engine(200)
wheels = Wheels(4)
my_car = Car("Honda", engine, wheels)
print(my_car.drive()) # Honda: Engine with 200HP started and 4 wheels rotating
These principles help create maintainable, reusable, and scalable code!