Back to Python

Python OOP Fundamentals

Classes and Objects

Classes are blueprints for creating objects. Objects are instances of classes that encapsulate data and functionality.

# Defining a class
class Dog:
    # Class attribute (shared by all instances)
    species = 'Canis familiaris'

    def __init__(self, name, age):
        # Instance attributes
        self.name = name
        self.age = age

    def description(self):
        return f"{self.name} is {self.age} years old"

# Creating objects (instances)
dog1 = Dog("Buddy", 5)
dog2 = Dog("Milo", 3)

# Accessing attributes and methods
print(dog1.name) # Buddy
print(dog2.description()) # Milo is 3 years old
print(dog1.species) # Canis familiaris

Inheritance

Inheritance allows a class to inherit attributes and methods from another class, promoting code reuse.

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} barks"

class Cat(Animal):
    def speak(self):
        return f"{self.name} meows"

# Using the classes
animal = Animal("Generic")
dog = Dog("Buddy")
cat = Cat("Whiskers")

print(animal.speak()) # Generic makes a sound
print(dog.speak()) # Buddy barks
print(cat.speak()) # Whiskers meows

Encapsulation

Encapsulation is the bundling of data with the methods that operate on that data, restricting direct access to some components.

class BankAccount:
    def __init__(self, account_holder, initial_balance=0):
        self._account_holder = account_holder # Protected attribute
        self.__balance = initial_balance # Private attribute

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return True
        return False

    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            return True
        return False

    def get_balance(self):
        return self.__balance

# Using the class
account = BankAccount("Alice", 1000)
account.deposit(500)
account.withdraw(200)
print(account.get_balance()) # 1300
# print(account.__balance) # Error - private attribute

Polymorphism

Polymorphism allows methods to do different things based on the object that is acting upon them.

class Bird:
    def fly(self):
        return "This bird can fly"

class Penguin(Bird):
    def fly(self):
        return "This penguin cannot fly"

class Eagle(Bird):
    def fly(self):
        return "This eagle soars high"

# Polymorphic function
def bird_flying_test(bird):
    print(bird.fly())

# Using the classes
bird = Bird()
penguin = Penguin()
eagle = Eagle()

bird_flying_test(bird) # This bird can fly
bird_flying_test(penguin) # This penguin cannot fly
bird_flying_test(eagle) # This eagle soars high

Special Methods (Dunder Methods)

Special methods in Python are surrounded by double underscores (dunder) and allow classes to define behavior for built-in operations.

class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages

    def __str__(self):
        return f"{self.title} by {self.author}"

    def __len__(self):
        return self.pages

    def __eq__(self, other):
        return self.title == other.title and self.author == other.author

# Using the class
book1 = Book("Python Crash Course", "Eric Matthes", 544)
book2 = Book("Fluent Python", "Luciano Ramalho", 792)

print(book1) # Python Crash Course by Eric Matthes
print(len(book2)) # 792
print(book1 == Book("Python Crash Course", "Eric Matthes", 500)) # True

Python OOP Videos

Master Python OOP with these handpicked YouTube tutorials:

OOP Basics

Learn the fundamentals of object-oriented programming:

Inheritance & Polymorphism

Advanced OOP concepts:

Python OOP Quiz