Object-Oriented Programming
Model domains with classes, inheritance, polymorphism, and Python special methods.
Classes and Objects
Classes define attributes and methods. __init__ initializes instance state. self refers to the current instance.
Instance attributes live on objects; class attributes are shared. Use @classmethod and @staticmethod for alternate constructors and utility functions tied to the class namespace.
Dataclasses reduce boilerplate for data containers with auto-generated __init__, __repr__, and equality.
- Prefer composition over deep inheritance hierarchies
- Use @property for computed attributes with validation
- Keep __init__ lightweight; defer heavy work to factories
@dataclass
class Product:
id: int
name: str
price: float
def with_tax(self, rate: float) -> float:
return self.price * (1 + rate)Inheritance and super
Subclass with class Child(Parent): and override methods. super() calls parent implementations—critical in __init__ chains and cooperative multiple inheritance.
Abstract base classes in abc module enforce interfaces. Raise NotImplementedError in base methods when ABC is overkill.
Favor duck typing: if it quacks like a file object, accept it without isinstance checks when behavior is the contract.
- Document extension points for subclasses
- Avoid calling super().__init__ twice accidentally
- Use Protocol for structural typing in modern codebases
class AdminUser(User):
def permissions(self):
base = super().permissions()
return base | {"admin": True}Dunder Methods
Special methods customize behavior: __str__ for readable prints, __repr__ for developers, __eq__ for equality, __len__ for len().
Context managers implement __enter__ and __exit__ for with blocks. Iterators use __iter__ and __next__.
Implement only dunder methods that match your object semantics—do not add __add__ unless addition is meaningful.
- __repr__ should ideally be unambiguous for debugging
- Use @functools.total_ordering when implementing rich comparisons
- Context managers guarantee cleanup in __exit__ even on exceptions
def __repr__(self):
return f"Order(id={self.id!r}, total={self.total!r})"