Skip to content

Advanced Python Classes and OOP

This guide covers advanced Python class concepts and object-oriented programming patterns.

Table of Contents

Introduction

What are Classes?

Classes in Python are used to create new types of objects, encapsulating data and behavior. They provide a way to organize code and create reusable components.

Key Concepts

  • Encapsulation
  • Inheritance
  • Polymorphism
  • Abstraction

Class Design

Basic Class Structure

class Account:
    def __init__(self, owner, balance):
        self.owner = owner
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount

    def withdraw(self, amount):
        self.balance -= amount

Class Variables vs Instance Variables

1
2
3
4
5
6
7
class Account:
    num_accounts = 0  # Class variable

    def __init__(self, owner, balance):
        self.owner = owner      # Instance variable
        self.balance = balance  # Instance variable
        Account.num_accounts += 1

Inheritance and Composition

Inheritance

1
2
3
4
5
6
7
class Animal:
    def speak(self):
        raise NotImplementedError

class Dog(Animal):
    def speak(self):
        return "Woof!"

Composition

class Stack:
    def __init__(self):
        self._items = list()

    def push(self, item):
        self._items.append(item)

    def pop(self):
        return self._items.pop()

    def __len__(self):
        return len(self._items)

Dependency Injection

class Stack:
    def __init__(self, *, container=None):
        if container is None:
            container = list()
        self._items = container

    def push(self, item):
        self._items.append(item)

    def pop(self):
        return self._items.pop()

Special Methods

Basic Special Methods

class Account:
    def __init__(self, owner, balance):
        self.owner = owner
        self.balance = balance

    def __repr__(self):
        return f'{type(self).__name__}({self.owner!r}, {self.balance!r})'

    def __str__(self):
        return f'Account of {self.owner} with balance {self.balance}'

Container Methods

class AccountPortfolio:
    def __init__(self):
        self.accounts = []

    def __len__(self):
        return len(self.accounts)

    def __getitem__(self, index):
        return self.accounts[index]

    def __iter__(self):
        return iter(self.accounts)

Context Manager Methods

class DatabaseConnection:
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.connection = None

    def __enter__(self):
        self.connection = connect(self.host, self.port)
        return self.connection

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.connection:
            self.connection.close()

Class Patterns

Factory Pattern

1
2
3
4
5
6
7
8
class AnimalFactory:
    @staticmethod
    def create_animal(animal_type):
        if animal_type == "dog":
            return Dog()
        elif animal_type == "cat":
            return Cat()
        raise ValueError(f"Unknown animal type: {animal_type}")

Singleton Pattern

1
2
3
4
5
6
7
class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

Observer Pattern

class Subject:
    def __init__(self):
        self._observers = []

    def attach(self, observer):
        self._observers.append(observer)

    def notify(self):
        for observer in self._observers:
            observer.update()

Best Practices

  1. Composition Over Inheritance
  2. Prefer composition for code reuse
  3. Use inheritance for "is-a" relationships
  4. Avoid deep inheritance hierarchies

  5. Encapsulation

  6. Use private attributes with _ prefix
  7. Provide public methods for access
  8. Use properties for controlled access

  9. Interface Design

  10. Keep interfaces small and focused
  11. Use abstract base classes for interfaces
  12. Document expected behavior

  13. Error Handling

  14. Use custom exceptions
  15. Provide meaningful error messages
  16. Handle errors at appropriate levels

  17. Data Model

  18. Descriptors
  19. Iterators
  20. Metaclasses