Advanced Object-Oriented Programming

Python OOPFree Lesson

Advertisement

Advanced Object-Oriented Programming

Abstract classes, metaclasses, descriptors, slots, and advanced OOP patterns.

Overview

Master advanced OOP concepts in Python.

Abstract Classes

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def perimeter(self):
        pass
    
    def describe(self):
        return f"{self.__class__.__name__} with area {self.area()}"

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

# shape = Shape()  # Error: Can't instantiate abstract class

circle = Circle(5)
print(circle.describe())  # Circle with area 78.53975

Metaclasses

class SingletonMeta(type):
    _instances = {}
    
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

class Database(metaclass=SingletonMeta):
    def __init__(self):
        self.connection = "Connected"

db1 = Database()
db2 = Database()
print(db1 is db2)  # True

Descriptors

class Property:
    def __init__(self, fget, fset=None):
        self.fget = fget
        self.fset = fset
    
    def __get__(self, obj, objtype=None):
        return self.fget(obj)
    
    def __set__(self, obj, value):
        if self.fset:
            self.fset(obj, value)
    
    def setter(self, fset):
        return Property(self.fget, fset)

class Temperature:
    def __init__(self):
        self._celsius = 0
    
    @Property
    def celsius(self):
        return self._celsius
    
    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("Temperature below absolute zero")
        self._celsius = value
    
    @Property
    def fahrenheit(self):
        return self._celsius * 9/5 + 32
    
    @fahrenheit.setter
    def fahrenheit(self, value):
        self.celsius = (value - 32) * 5/9

temp = Temperature()
temp.celsius = 25
print(temp.fahrenheit)  # 77.0

slots

class Point:
    __slots__ = ['x', 'y']
    
    def __init__(self, x, y):
        self.x = x
        self.y = y

# Memory efficient
p = Point(1, 2)
# p.z = 3  # Error: 'Point' object has no attribute 'z'

Practice

Implement a singleton pattern for a configuration manager.

Advertisement

Need Expert Python Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement