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.