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:
Learn the fundamentals of object-oriented programming:
Inheritance & Polymorphism
Advanced OOP concepts:
Common OOP design patterns: