# How Object-Oriented Programming (OOP) Is Presented in Day 21 of 30 Days of Python

> Explore how Day 21 of 30 Days of Python introduces Object-Oriented Programming OOP with classes, inheritance, and encapsulation. Learn to build structured Python code.

- Repository: [Asabeneh/30-Days-Of-Python](https://github.com/Asabeneh/30-Days-Of-Python)
- Tags: deep-dive
- Published: 2026-03-06

---

**Day 21 introduces OOP by progressing from basic class syntax to inheritance and encapsulation in the [`21_Day_Classes_and_objects/21_classes_and_objects.md`](https://github.com/Asabeneh/30-Days-Of-Python/blob/main/21_Day_Classes_and_objects/21_classes_and_objects.md) tutorial, establishing the foundation for reusable, structured Python code.**

The `Asabeneh/30-Days-Of-Python` repository uses Day 21 to transition learners from procedural scripting to **object-oriented programming (OOP)**. The lesson, contained in [`21_Day_Classes_and_objects/21_classes_and_objects.md`](https://github.com/Asabeneh/30-Days-Of-Python/blob/main/21_Day_Classes_and_objects/21_classes_and_objects.md), demonstrates Python's class-based architecture through practical examples that range from simple constructors to complex inheritance hierarchies.

## Core OOP Concepts Covered in Day 21

### Class Definition and the `class` Keyword

The tutorial opens by defining a **class** as a blueprint for creating objects. It demonstrates the `class` keyword syntax and explains how classes bundle data (attributes) and functionality (methods) into a single structure. According to the source file, this encapsulation allows developers to model real-world entities like people, vehicles, or accounts as distinct, self-contained units.

### The Constructor and Instance Attributes

A significant portion of the chapter focuses on the **`__init__` method**, Python's initializer for setting up new objects. The guide explains that `self` represents the instance being created and shows how to bind unique data—such as `name` and `age`—to each object. This establishes the pattern of storing state within instances rather than relying on global variables.

### Instance Methods vs. Class Attributes

The lesson distinguishes between **instance methods**, which operate on `self` and access specific object data, and **class attributes**, which are shared across all instances. The tutorial illustrates this by defining a `species` attribute on a `Person` class that every instance inherits but cannot modify independently, demonstrating Python's flexible attribute resolution order.

### Encapsulation and Private Attributes

Day 21 addresses **encapsulation** by introducing the single-underscore naming convention (e.g., `_salary`) to indicate attributes intended for internal use. The source explains that Python lacks strict private modifiers found in other languages, relying instead on developer conventions to signal that certain attributes should not be accessed directly from outside the class.

### Inheritance and Method Overriding

The tutorial extends the `Person` example by creating an **`Employee` subclass** that inherits all parent attributes while adding job-specific data like `title`. It demonstrates **`super().__init__()`** to invoke the parent constructor, ensuring base attributes are initialized without code duplication. The chapter then shows **method overriding**, where `Employee` redefines the `greet` method to include professional details while still leveraging the parent's logic via `super()`.

### Special Methods for Object Representation

To improve debugging and output readability, the guide introduces **special methods** (dunder methods) `__str__` and `__repr__`. These methods define how objects appear when printed or inspected in REPL environments, allowing developers to control the string representation of their classes rather than relying on default memory addresses.

### Polymorphism and Practical Application

The final section covers **polymorphism** by demonstrating how functions can accept any object that implements a common interface, regardless of the specific class. The tutorial culminates in a practical exercise modeling a **Vehicle** hierarchy, requiring readers to create base and subclasses, instantiate objects, and call methods interchangeably to reinforce the concepts.

## Code Examples from the Tutorial

The following snippets reflect the progression found in [`21_Day_Classes_and_objects/21_classes_and_objects.md`](https://github.com/Asabeneh/30-Days-Of-Python/blob/main/21_Day_Classes_and_objects/21_classes_and_objects.md).

### 1. Basic Class with Constructor and Class Attribute

```python
class Person:
    """A blueprint for person objects."""
    
    species = "Homo sapiens"  # Class attribute shared by all instances

    
    def __init__(self, name: str, age: int):
        self.name = name      # Instance attribute unique to each object

        self.age = age
    
    def greet(self) -> str:
        """Instance method accessing self attributes."""
        return f"Hello, my name is {self.name}."

# Usage

alice = Person("Alice", 30)
print(alice.greet())         # Hello, my name is Alice.

print(Person.species)        # Homo sapiens

```

### 2. Inheritance with `super()` and Method Overriding

```python
class Employee(Person):
    """Specialized Person with employment details."""
    
    def __init__(self, name: str, age: int, title: str):
        super().__init__(name, age)  # Initialize parent class attributes

        self.title = title
    
    def greet(self) -> str:
        """Override to add professional context."""
        return f"{super().greet()} I work as a {self.title}."

# Usage

bob = Employee("Bob", 45, "Data Scientist")
print(bob.greet())

# Hello, my name is Bob. I work as a Data Scientist.

```

### 3. Special Methods for Debugging and Display

```python
class Vehicle:
    """Demonstrates __repr__ and __str__ usage."""
    
    def __init__(self, make: str, model: str):
        self.make = make
        self.model = model
    
    def __repr__(self) -> str:
        """Developer-friendly representation."""
        return f"Vehicle(make={self.make!r}, model={self.model!r})"
    
    def __str__(self) -> str:
        """User-friendly representation."""
        return f"{self.make} {self.model}"

car = Vehicle("Toyota", "Corolla")
print(repr(car))   # Vehicle(make='Toyota', model='Corolla')

print(str(car))    # Toyota Corolla

```

### 4. Polymorphic Function Accepting Any Object

```python
def describe(obj):
    """Works with any object implementing __str__."""
    print(str(obj))

describe(bob)   # Employee instance

describe(car)   # Vehicle instance

```

## Summary

- **Day 21** in the *30 Days of Python* series is the definitive introduction to OOP, located at [`21_Day_Classes_and_objects/21_classes_and_objects.md`](https://github.com/Asabeneh/30-Days-Of-Python/blob/main/21_Day_Classes_and_objects/21_classes_and_objects.md).
- The tutorial teaches **class definition**, the **`__init__` constructor**, and the distinction between **instance** and **class attributes**.
- It demonstrates **inheritance** using `super()` to extend base classes and **method overriding** to customize behavior.
- **Encapsulation** is taught through Python's underscore convention rather than strict access control.
- **Special methods** like `__str__` and `__repr__` are introduced to control object representation.
- A final **Vehicle hierarchy exercise** reinforces polymorphism and practical OOP design.

## Frequently Asked Questions

### What file contains the Day 21 OOP tutorial in the 30 Days of Python repository?

The complete lesson resides in [`21_Day_Classes_and_objects/21_classes_and_objects.md`](https://github.com/Asabeneh/30-Days-Of-Python/blob/main/21_Day_Classes_and_objects/21_classes_and_objects.md) within the `Asabeneh/30-Days-Of-Python` repository. This markdown file contains explanations, code snippets, and exercises covering classes, objects, and inheritance.

### Does Day 21 cover inheritance and polymorphism?

Yes. The tutorial explicitly covers **inheritance** by creating a subclass (`Employee`) that inherits from a parent class (`Person`), uses `super()` to call the parent constructor, and overrides methods. It also introduces **polymorphism** by showing how functions can operate on any object that shares a common interface.

### How does the tutorial explain encapsulation in Python?

The source explains that Python uses naming conventions—specifically a single leading underscore (e.g., `_attribute`)—to indicate attributes intended for internal use. Unlike languages with strict `private` or `protected` keywords, Python relies on the "we're all consenting adults" philosophy, where the underscore signals that an attribute should not be accessed directly from outside the class.

### What is the practical exercise at the end of Day 21?

The chapter concludes with a **Vehicle modeling project** where readers must create a base `Vehicle` class and specialized subclasses (such as `Car` or `Bus`). The exercise requires implementing constructors, methods, and inheritance to instantiate objects and demonstrate polymorphic behavior, reinforcing the OOP concepts taught throughout the lesson.