Slide 1: Introduction to Object-Oriented Programming (OOP)
Object-Oriented Programming is a programming paradigm that organizes code into objects, which are instances of classes. OOP focuses on the concept of objects that contain data and code, emphasizing the relationships between objects to design and structure programs.
class Car:
def __init__(self, make, model):
self.make = make
self.model = model
def display_info(self):
return f"{self.make} {self.model}"
my_car = Car("Toyota", "Corolla")
print(my_car.display_info())Slide 2: Encapsulation
Encapsulation is the bundling of data and the methods that operate on that data within a single unit (class). It restricts direct access to some of an object's components, which is a means of preventing accidental interference and misuse of the methods and data.
class BankAccount:
def __init__(self):
self.__balance = 0
def deposit(self, amount):
if amount > 0:
self.__balance += amount
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
def get_balance(self):
return self.__balance
account = BankAccount()
account.deposit(1000)
print(account.get_balance())Slide 3: Polymorphism - Method Overriding
Polymorphism allows objects of different classes to be treated as objects of a common base class. Method overriding is a form of polymorphism where a subclass provides a specific implementation of a method that is already defined in its superclass.
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
def animal_sound(animal):
return animal.speak()
dog = Dog()
cat = Cat()
print(animal_sound(dog))
print(animal_sound(cat))Slide 4: Polymorphism - Method Overloading
Python doesn't support method overloading by default, but we can simulate it using default arguments or variable-length arguments.
class Calculator:
def add(self, *args):
return sum(args)
calc = Calculator()
print(calc.add(2, 3))
print(calc.add(2, 3, 4))
print(calc.add(2, 3, 4, 5))Slide 5: Composition
Composition is a design principle that states that classes should achieve polymorphic behavior and code reuse by their composition rather than inheritance from a base or parent class.
class Engine:
def start(self):
return "Engine started"
class Car:
def __init__(self):
self.engine = Engine()
def start(self):
return self.engine.start()
my_car = Car()
print(my_car.start())Slide 6: Abstraction
Abstraction is the process of hiding the internal details and showing only the functionality. In Python, we can achieve abstraction using abstract base classes.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side ** 2
square = Square(5)
print(square.area())Slide 7: Aggregation
Aggregation is a special form of association where objects have a separate lifecycle but share ownership. It represents a "has-a" relationship between objects.
class Department:
def __init__(self, name):
self.name = name
class Employee:
def __init__(self, name, department):
self.name = name
self.department = department
dep = Department("IT")
emp1 = Employee("Alice", dep)
emp2 = Employee("Bob", dep)
print(f"{emp1.name} works in {emp1.department.name}")
print(f"{emp2.name} works in {emp2.department.name}")Slide 8: Association
Association represents a relationship between two or more objects where all objects have their own lifecycle and there is no owner. It can be one-to-one, one-to-many, or many-to-many.
class Student:
def __init__(self, name):
self.name = name
self.courses = []
def enroll(self, course):
self.courses.append(course)
course.add_student(self)
class Course:
def __init__(self, name):
self.name = name
self.students = []
def add_student(self, student):
self.students.append(student)
student1 = Student("Alice")
course1 = Course("Python Programming")
student1.enroll(course1)
print(f"{student1.name} is enrolled in {student1.courses[0].name}")
print(f"{course1.name} has {course1.students[0].name} as a student")Slide 9: Inheritance
Inheritance is a mechanism where a class can derive properties and characteristics from another class. It supports the concept of hierarchical classification and code reuse.
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
pass
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says Meow!"
dog = Dog("Buddy")
cat = Cat("Whiskers")
print(dog.speak())
print(cat.speak())Slide 10: Multiple Inheritance
Python supports multiple inheritance, allowing a class to inherit from multiple parent classes. This can lead to powerful combinations of behaviors but should be used carefully to avoid complexity.
class Flyer:
def fly(self):
return "I can fly!"
class Swimmer:
def swim(self):
return "I can swim!"
class Duck(Flyer, Swimmer):
pass
duck = Duck()
print(duck.fly())
print(duck.swim())Slide 11: Method Resolution Order (MRO)
When using multiple inheritance, Python uses the C3 Linearization algorithm to determine the order in which base classes are searched when looking for a method. This is known as the Method Resolution Order (MRO).
class A:
def method(self):
return "A"
class B(A):
def method(self):
return "B"
class C(A):
def method(self):
return "C"
class D(B, C):
pass
d = D()
print(d.method())
print(D.mro())Slide 12: Property Decorators
Property decorators provide a way to customize access to class attributes, allowing you to define methods that can be accessed like 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
@property
def fahrenheit(self):
return (self.celsius * 9/5) + 32
temp = Temperature(25)
print(f"Celsius: {temp.celsius}")
print(f"Fahrenheit: {temp.fahrenheit}")
temp.celsius = 30
print(f"New Celsius: {temp.celsius}")
print(f"New Fahrenheit: {temp.fahrenheit}")Slide 13: Static and Class Methods
Static methods and class methods are special methods that can be called on a class without creating an instance of the class. They serve different purposes and have different behaviors.
class MathOperations:
@staticmethod
def add(x, y):
return x + y
@classmethod
def multiply(cls, x, y):
return cls.add(x, 0) * y
print(MathOperations.add(5, 3))
print(MathOperations.multiply(4, 2))Slide 14: Additional Resources
For further exploration of Object-Oriented Programming concepts and their implementation in Python, consider the following resources:
- "Object-Oriented Programming in Python: A Comprehensive Study" by Bhargavi et al. (2023) ArXiv URL: https://arxiv.org/abs/2308.15827
- "Python Design Patterns" by Chetan Giridhar (Book)
- "Fluent Python" by Luciano Ramalho (Book)
- Python's official documentation on classes: https://docs.python.org/3/tutorial/classes.html
These resources provide in-depth explanations and advanced techniques for mastering OOP in Python.