Object-oriented programming (OOP) in Python – classes, objects, inheritance, encapsulation, and polymorphism.
The four principles
OOP in Python rests on four ideas:
- Encapsulation: bundle data and the methods that work on it inside a class. Hide internal state from the outside.
- Abstraction: expose only what callers need. Hide the complexity underneath.
- Inheritance: build new classes from existing ones. Reuse code without rewriting it.
- Polymorphism: define methods in a child class with the same name as in the parent.
Classes and objects
A class is a blueprint. An object is an instance of that class – it has attributes (data) and methods (behaviour).
Defining a class
class Dog:
# Class Attribute
species = "Canis familiaris"
# Initializer / Instance attributes
def __init__(self, name, age):
self.name = name
self.age = age
# instance method
def description(self):
return f"{self.name} is {self.age} years old"
# Another instance method
def speak(self, sound):
return f"{self.name} says {sound}"
Creating objects
# Instantiate the Dog class
mikey = Dog("Mikey", 6)
# Access the instance attributes
print(f"{mikey.name} is {mikey.age} years old") # Mikey is 6 years old
# Is Mikey a mammal?
if mikey.species == "Canis familiaris":
print(f"{mikey.name} is a {mikey.species}") # Mikey is a Canis familiaris
Inheritance
A child class inherits methods and attributes from its parent:
# Parent class
class Dog:
# ... (as above)
# Child class (inherits from Dog class)
class RussellTerrier(Dog):
def run(self, speed):
return f"{self.name} runs {speed}"
# Child class (inherits from Dog class)
class Bulldog(Dog):
def run(self, speed):
return f"{self.name} runs {speed}"
# Child instances
jim = Bulldog("Jim", 12)
print(jim.description()) # Jim is 12 years old
# Child classes inherit attributes and
# behaviors from the parent class
print(jim.run("slowly")) # Jim runs slowly
Encapsulation
Prefix an attribute with double underscores to make it private (name-mangled). Access it through methods instead:
class Computer:
def __init__(self):
self.__maxprice = 900
def sell(self):
print(f"Selling Price: {self.__maxprice}")
def setMaxPrice(self, price):
self.__maxprice = price
c = Computer()
c.sell() # Selling Price: 900
# change the price
c.__maxprice = 1000
c.sell() # Selling Price: 900
# using setter function
c.setMaxPrice(1000)
c.sell() # Selling Price: 1000
Polymorphism
Different classes can define a method with the same name. The right version runs depending on the object:
class Dog:
def speak(self):
return "Woof!"
class Cat:
def speak(self):
return "Meow!"
def get_pet_speak(pet):
print(pet.speak())
# Driver code
dog = Dog()
get_pet_speak(dog) # Outputs: Woof!
cat = Cat()
get_pet_speak(cat) # Outputs: Meow!
OOP gives you a way to structure code around the things your program models. Start with small classes and build up as the problem demands.

