By the end of this lesson, you will be able to define Python classes, create objects, and apply inheritance and polymorphism to structure code logically.
What it is
Object-Oriented Programming (OOP) is a paradigm that organizes software design around data, or "objects," rather than functions and logic. An object is an instance of a class, which acts as a blueprint defining properties (attributes) and behaviors (methods). Key pillars include encapsulation (bundling data with methods), inheritance (creating new classes from existing ones), and polymorphism (using a single interface for different underlying forms). In Python, everything is an object, making OOP fundamental to the language's architecture.Why it matters
- Modularity: Code is broken into reusable components, making large projects easier to manage.
- Maintainability: Changes in one class rarely break unrelated parts of the application.
- Reusability: Classes can be extended via inheritance, reducing code duplication.
- Real-world Modeling: It allows developers to map complex real-world entities directly to code structures.
Syntax or steps
1. Define a class using theclass keyword followed by the name.
2. Initialize attributes in the __init__ method, using self to refer to the current instance.
3. Define methods inside the class; they must also accept self as the first argument.
4. Create instances (objects) by calling the class like a function.
5. Use inheritance by passing the parent class name in parentheses after the child class name.
Example
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name} makes a sound."
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says Meow!"
# Polymorphism in action
animals = [Dog("Buddy"), Cat("Whiskers")]
for animal in animals:
print(animal.speak())
Explanation: The Animal class serves as the base. Dog and Cat inherit from Animal but override the speak method. When iterating through the list, Python calls the specific speak method of each object type, demonstrating polymorphism.
Common mistakes
- Forgetting
self: Methods must includeselfas their first parameter to access instance variables. Omitting it causesTypeError. - Mutable Default Arguments: Avoid assigning lists or dictionaries as default values in
__init__; they are shared across all instances. UseNoneand initialize inside the method instead. - Overcomplicating Inheritance: Deep inheritance chains make debugging difficult. Prefer composition (having objects contain other objects) over deep hierarchy when possible.
- Ignoring Encapsulation: Accessing private attributes (prefixed with
_or__) directly from outside the class breaks encapsulation principles. Use getter/setter methods if needed.
When to use it
Compare OOP with Procedural Programming below.| Feature | OOP (Classes/Objects) | Procedural (Functions) |
|---|---|---|
| Best For | Large, complex systems with stateful entities. | Small scripts, linear tasks, or simple calculations. |
| Data Handling | Bundles data and behavior together. | Data passed explicitly between functions. |
| Extensibility | High via inheritance and polymorphism. | Lower; requires modifying existing code. |
Practice
Guided Exercise: Create aCar class with attributes make and model. Add a method drive() that prints "The {make} {model} is driving." Instantiate two cars and call the method.
Challenge: Extend the
Car class to create an ElectricCar subclass. Override the drive() method to add "silently" to the output.
Hint: Use
super().__init__() in the child class to handle parent initialization.
Quick check
Question: What happens if you forget to passself as the first argument in a class method?
Answer: Python raises a
TypeError because the method expects an instance reference to access attributes, but receives none (or incorrect arguments).
Summary
Python’s OOP features allow you to model real-world entities through classes and objects. By mastering inheritance and polymorphism, you can write flexible, reusable code that scales effectively. Always remember thatself is the bridge between the class definition and the specific instance being used.