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 AcademyThe 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.