02Module · Goodrich Ch. 2

Week 2 — Object-Oriented Programming & Design

OO design goals, special methods, operator overloading, inheritance, abstract base classes, name resolution, and deep vs shallow copy.

Object-Oriented Programming & Design

Designing reusable abstractions with classes, special methods, inheritance hierarchies, and Python's ABCs.

Theory

Three OO design goals: robustness (handles bad input), adaptability (survives change), reusability (works in new contexts).

Special (dunder) methods let user-defined classes participate in Python's syntax — +, len(), iter(), with-statements.

Inheritance models is-a relationships; composition models has-a. Prefer composition unless behavior is genuinely subtype.

Abstract base classes (abc module) declare the contract a subclass must satisfy.

Key points

  • __eq__ should be consistent with __hash__ for hashable types.
  • copy.copy() is shallow; copy.deepcopy() recurses into nested objects.
  • Method resolution follows the MRO (C3 linearization); super() walks the MRO, not the parent.

Code examples

A Vector with operator overloading
A Vector with operator overloading
class Vector:
    def __init__(self, data):
        self._data = list(data)

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

    def __getitem__(self, i):
        return self._data[i]

    def __add__(self, other):
        if len(self) != len(other):
            raise ValueError("dimension mismatch")
        return Vector(a + b for a, b in zip(self, other))

    def __eq__(self, other):
        return list(self) == list(other)

    def __repr__(self):
        return f"Vector({self._data!r})"

print(Vector([1, 2, 3]) + Vector([4, 5, 6]))
Abstract base class
Abstract base class
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        ...

class Circle(Shape):
    def __init__(self, r): self.r = r
    def area(self): return 3.14159 * self.r ** 2