Skip to lesson content

PYTHON / LESSON 13 OF 18

Object oriented programming

Read the explanations, work through the examples, and complete the student tasks.

Learning goals

Create classes and instances, initialize state, and use inheritance, polymorphism, encapsulation, and abstraction.

Explanation

A class defines behavior and attributes for objects. An instance is one object created from the class. self refers to the instance receiving a method call. __init__ initializes a new instance; more precisely, __new__ creates it before __init__ runs.

Instance attributes belong to individual objects. Class attributes are shared through class lookup. Inheritance lets a subclass specialize a parent. Polymorphism means different objects can respond to the same operation. Encapsulation keeps changes behind a clear interface. A leading underscore marks an internal attribute by convention; it is not security. Double underscores trigger name mangling rather than absolute privacy.

Example 1 Student objects and specialization

class Student:
    school = "Python Academy"

    def __init__(self, name, score):
        self.name = name
        self._score = score

    def result(self):
        return f"{self.name}: {self._score}"

class HonorsStudent(Student):
    def result(self):
        return super().result() + " (honors)"

students = [Student("Ali", 75), HonorsStudent("Sara", 95)]
for student in students:
    print(student.result())
print(students[0].school)

Expected output:

Ali: 75
Sara: 95 (honors)
Python Academy

The loop does not need to know which subclass it receives. Each object supplies its own result method. super reuses the parent's implementation.

Example 2 An abstract interface

from abc import ABC, abstractmethod

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

class Rectangle(Shape):
    def __init__(self, width, height):
        if width < 0 or height < 0:
            raise ValueError("Dimensions cannot be negative")
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

rectangle = Rectangle(4, 6)
print(rectangle.area())

Expected output: 24. Shape declares a required operation. Rectangle provides it. Instantiating Shape itself raises TypeError because its abstract method is not implemented. Validation prevents an invalid object from being initialized with negative dimensions.

Common mistakes

Do not put a mutable per-instance list on the class: all instances can share it accidentally. Create such lists inside __init__. Inheritance is not required for every reuse problem; an object can hold another object and delegate work to it.

Student tasks

1. Create Book with title, author, and a describe method. Instantiate two books with different state.

2. Create Account with an internal balance, deposit, and a read-only balance property. Reject nonpositive deposits.

3. Add Circle as a Shape subclass and implement area with math.pi. Test radius 0 and radius 2.

4. Put rectangles and circles in one list and print each area using the same loop.

Completion check: demonstrate separate object state, validation, and polymorphic calls.