Python course menu
Python Classes Explained: Your First Steps in Object-Oriented Programming
Learn Python classes from scratch: what a class is, define one with class, __init__ and self, add methods, class vs instance attributes, and readable printing with __str__ and __repr__.
On this page
So far you have stored data in variables, lists and dictionaries, and written separate functions to work with it. Object-oriented programming (OOP) bundles the data and the functions that work on it together into objects. A class is the blueprint that describes what those objects contain and can do.
Why classes?#
Imagine a banking program. Each account has an owner and a balance, and can accept deposits and withdrawals. You could use a dictionary plus separate functions, but a class keeps everything about "a bank account" in one place:
- attributes: the data each object holds (
owner,balance) - methods: functions that belong to the object (
deposit(),withdraw())
One class can create any number of independent objects, or instances, just as one house blueprint can build many houses.
Defining a class#
class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed
def bark(self):
return f"{self.name} says woof!"
rex = Dog("Rex", "Labrador")
bella = Dog("Bella", "Beagle")
print(rex.bark())
print(bella.name, bella.breed)
print(type(rex).__name__)Rex says woof!
Bella Beagle
DogPiece by piece:
What is self?#
self is the object the method is working on. When you call rex.bark(), Python automatically passes rex as self. That is how one bark method can produce "Rex says woof!" for one dog and "Bella says woof!" for another.
You never pass self yourself; Python does it. But every method must list it as its first parameter.
A more useful class#
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
return self.balance
def withdraw(self, amount):
if amount > self.balance:
raise ValueError("Insufficient funds")
self.balance -= amount
return self.balance
acc = BankAccount("Asha", 1000)
print(acc.deposit(500))
print(acc.withdraw(300))
print(acc.owner, acc.balance)
try:
acc.withdraw(5000)
except ValueError as e:
print(e)1500
1200
Asha 1200
Insufficient fundsThe rules about balances live inside the class, next to the data they protect.
Class attributes vs instance attributes#
- Instance attributes (set with
self.x = ...) belong to one object. - Class attributes (set directly in the class body) are shared by all objects of the class.
class Dog:
species = "Canis familiaris" # class attribute: shared
def __init__(self, name):
self.name = name # instance attribute: per object
a = Dog("Rex")
b = Dog("Bella")
print(a.species, b.species, Dog.species)
print(a.name, b.name)Canis familiaris Canis familiaris Canis familiaris
Rex BellaA class attribute can also count how many objects have been created:
class Counter:
count = 0
def __init__(self):
Counter.count += 1
Counter(); Counter(); Counter()
print(Counter.count)3Printing objects nicely#
By default, printing an object is not very helpful:
print(rex)<__main__.Dog object at 0x0000024A616D1400>(The address differs on every run.) Define __str__ for a friendly description and __repr__ for a developer-oriented one:
class Dog:
def __init__(self, name):
self.name = name
def __str__(self):
return f"Dog named {self.name}"
def __repr__(self):
return f"Dog({self.name!r})"
rex = Dog("Rex")
print(rex)
print([rex])Dog named Rex
[Dog('Rex')]print() uses __str__; containers like lists and the interactive shell use __repr__. Methods with double underscores on both sides are called special or dunder methods; Python calls them for you in specific situations.
Common mistakes#
Practice#
Practice exercise
Write a Rectangle class with width and height, and methods area(), perimeter() and is_square(). Test it with a 4 × 6 rectangle and a 5 × 5 square.
Show hint
Store both values in __init__ with self.. Each method uses self.width and self.height.
Show solution
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
def is_square(self):
return self.width == self.height
r = Rectangle(4, 6)
s = Rectangle(5, 5)
print(r.area(), r.perimeter(), r.is_square())
print(s.area(), s.is_square())24 20 False
25 TrueKey takeaway#
Finished this lesson?