Chapter 11: Object-Oriented Programming

Learn how to define classes, create objects, manage inheritance and use Python’s special methods.

Download chapter11.py

Objectives

1. Classes & Instances

Define a class and its __init__ constructor:

class Person:
    def __init__(self, name, age):
        self.name = name      # instance attribute
        self.age = age

# Instantiate
alice = Person("Alice", 30)
print(alice.name, alice.age)  # Alice 30

2. Instance & Class Members

Instance methods operate on self; class variables shared across instances:

class Counter:
    total = 0              # class variable

    def __init__(self):
        Counter.total += 1
        self.id = Counter.total

    def greet(self):
        return f"Instance {self.id} says hello"

# Usage
c1 = Counter(); c2 = Counter()
print(c1.greet(), c2.greet())
print("Total instances:", Counter.total)

3. Inheritance & Polymorphism

Subclass to extend or override behavior:

class Animal:
    def speak(self):
        raise NotImplementedError

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

class Cat(Animal):
    def speak(self):
        return "Meow!"

for pet in (Dog(), Cat()):
    print(pet.speak())    # Woof! Meow!

4. Special Methods

Implement __str__, __repr__, __eq__ for rich behavior:

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __repr__(self):
        return f"Point({self.x},{self.y})"

    def __eq__(self, other):
        return isinstance(other, Point) and (self.x, self.y)==(other.x, other.y)

p1, p2 = Point(1,2), Point(1,2)
print(p1, p2, p1==p2)   # Point(1,2) Point(1,2) True

5. Encapsulation & @property

Use name mangling for “private” attributes and @property for getters/setters:

class Account:
    def __init__(self, bal):
        self.__balance = bal

    @property
    def balance(self):
        return self.__balance

    @balance.setter
    def balance(self, val):
        if val<0:
            raise ValueError("Negative balance")
        self.__balance = val

acct = Account(100)
print(acct.balance)      # 100
acct.balance = 150
# acct.balance = -50    # ValueError

Exercises

  1. Define a Rectangle class with width, height and a method area().
  2. Implement a Vehicle base class and subclasses Car, Bike overriding a move() method.
  3. Create a Vector class supporting +, -, * via __add__, __sub__, __mul__.
  4. Use @property to create a read-only full_name from first_name and last_name.