Object Oriented Programming (OOP)
OOP is a way of organising code by putting related data and functions together into classes.
- A class is a blueprint.
- An instance (or object) is something built from that blueprint.
Creating a class
class Person:
def __init__(self, name):
self.name = name
print("Created person:", name)
person1 = Person("Alice")
person2 = Person("Ben")
# Output:
# Created person: Alice
# Created person: Ben
Each time you create a Person, you get a separate instance.
Methods inside classes
A method is a function that belongs to a class. Methods always take self so they can access data stored in the object.
class Person:
def __init__(self, name):
self.name = name
def say_hello(self):
print(self.name, "says hello.")
p = Person("Mia")
p.say_hello()
# Output:
# Mia says hello.
The self keyword
self refers to the current object. It lets you read and change data stored inside that object.
class Pet:
def __init__(self, name):
self.name = name
def speak(self):
print(self.name, "makes a sound.")
cat = Pet("Willow")
dog = Pet("Rex")
cat.speak()
dog.speak()
# Output:
# Willow makes a sound.
# Rex makes a sound.
Class attributes vs instance attributes
Instance attributes
Unique for each object.
self.name
self.age
Class attributes
Shared across every instance.
class Animal:
species = "Mammal" # class attribute
def __init__(self, name):
self.name = name # instance attribute
a = Animal("Tiger")
b = Animal("Lion")
print(a.species)
print(b.species)
# Output:
# Mammal
# Mammal
Inheritance
Inheritance allows one class to reuse code from another.
class Device:
def power_on(self):
print("Device is now on.")
class Phone(Device):
pass
my_phone = Phone()
my_phone.power_on()
# Output:
# Device is now on.
Overriding methods
A subclass can replace a method from its parent.
class Device:
def power_on(self):
print("Powering on...")
class Laptop(Device):
def power_on(self):
print("Laptop booting up...")
lap = Laptop()
lap.power_on()
# Output:
# Laptop booting up...
Encapsulation
Encapsulation helps hide internal details. Making attributes private protects them.
class Wallet:
def __init__(self, amount):
self.__amount = amount # private
def add(self, value):
self.__amount += value
def get_balance(self):
return self.__amount
w = Wallet(50)
w.add(20)
print(w.get_balance())
# Output:
# 70
Trying to access w.__amount directly will fail.
Magic (Dunder) methods
These special methods begin and end with double underscores.
class Book:
def __init__(self, title):
self.title = title
def __str__(self):
return f"Book: {self.title}"
b = Book("Python Basics")
print(b)
# Output:
# Book: Python Basics
Useful magic methods
__str__— how the object is printed__len__— length of an object__eq__— how two objects are compared__add__— what it means to “add” two objects
Composition and aggregation
Composition means one object contains another as part of how it works.
class Engine:
def start(self):
print("Engine started.")
class Car:
def __init__(self):
self.engine = Engine() # composition
car = Car()
car.engine.start()
# Output:
# Engine started.