As programs grow, you often have several pieces of data that belong together and functions that work on that data. A bank account has an owner and a balance, and you deposit into it and withdraw from it. You could store the data in a dictionary and write separate functions, but Python offers a tidier option: a class.
A class is a blueprint for making objects. It describes what data each object holds, called its attributes, and what it can do, called its methods. From one Account class you can create as many account objects as you like, each with its own owner and balance. This style is called object-oriented programming (OOP).
You've been using objects all along: strings, lists and dictionaries are objects with methods such as upper() and append(). In this lesson you'll write your own classes, understand the famous self parameter, and give your objects a readable printed form.
Defining a class and creating objects
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
rex = Dog("Rex", 3)
bella = Dog("Bella", 5)
print(rex.name, bella.age) # Rex 5class Dog:starts the definition. Class names use CapWords by convention.__init__is a special method that runs automatically whenever a new object is created. It sets up the object's starting attributes.- Calling the class like a function,
Dog("Rex", 3), creates a new object, also called an instance. - Each object has its own attributes, reached with a dot:
rex.name.
What self means
Every method's first parameter is self: the particular object the method is working on. When you call rex.bark(), Python quietly turns it into Dog.bark(rex), so inside the method self is rex.
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
return f"{self.name} says woof!"self.name = name stores the argument on the object so other methods can use it later. Forgetting self. is a classic mistake: a plain name = name inside __init__ creates a temporary local variable that disappears when the method ends.
Methods that change the object
Methods can read and update the object's attributes, which keeps all the rules about the data in one place:
class Account:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("Deposit must be positive")
self.balance += amountBecause the check lives inside deposit(), no part of your program can accidentally add a negative amount, as long as it uses the method. Python doesn't strictly stop people changing attributes directly, but by convention a name starting with an underscore, such as _balance, means "internal: please use the methods".
Class attributes and __str__
An attribute defined directly in the class body, outside any method, is a class attribute, shared by every object. It suits values that are the same for all instances, such as an interest rate.
Printing an object normally shows something unhelpful like <__main__.Account object at 0x10f3>. Define __str__ to choose what print() and str() display:
def __str__(self):
return f"{self.owner}: £{self.balance:.2f}"Methods with double underscores on both sides are called dunder methods. Python calls them automatically in particular situations, and they let your objects work naturally with built-in functions.
How attribute lookup works
When you read obj.attribute, Python first looks on the object itself, then on its class. That explains how class attributes are shared, and why assigning through an object behaves differently:
class Account:
interest_rate = 0.02 # class attribute
a = Account()
b = Account()
a.interest_rate = 0.05 # creates an attribute on a only
print(a.interest_rate, b.interest_rate, Account.interest_rate)
# 0.05 0.02 0.02Assigning a.interest_rate didn't change the class; it gave a its own attribute that hides the shared one. To change the rate for everyone, assign to Account.interest_rate.
Objects are also compared by identity by default: two separate Account objects with identical balances are not == unless you define __eq__. The dataclasses lesson shows how to get sensible comparison for free, and magic methods covers __eq__, __repr__ and the rest.
Python Classes Syntax
Class syntax
class ClassName:
shared_value = 0 # class attribute
def __init__(self, param):
self.attribute = param # instance attribute
def method(self, arg):
return self.attribute + arg
def __str__(self):
return f"ClassName({self.attribute})"
obj = ClassName(value)
obj.method(arg)Python Classes Summary
- A class is a blueprint; an object (instance) is created by calling the class.
__init__(self, ...)sets up each new object's attributes.selfis the object a method is working on; store data withself.attribute.- Methods keep the rules for changing an object's data in one place.
- Class attributes are shared by all instances;
__str__controls how an object prints.
Python Classes Examples
Each example shows the code, the output it produces and what each part does.
A simple bank account
class Account:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if amount > self.balance:
return False
self.balance -= amount
return True
def __str__(self):
return f"{self.owner}: £{self.balance:.2f}"
acc = Account("Sam", 50)
acc.deposit(25)
print(acc.withdraw(100))
print(acc.withdraw(30))
print(acc)False
True
Sam: £45.00Line-by-line explanation
- Lines 2 to 4Each account starts with an owner and an optional balance.
- Lines 9 to 13The method refuses withdrawals larger than the balance and reports success with True or False.
- Lines 15 to 16__str__ decides what print(acc) shows.
- Lines 19 to 2150 + 25 = 75; the 100 withdrawal fails, the 30 succeeds, leaving 45.
Several objects with a class attribute
class Player:
max_health = 100
def __init__(self, name):
self.name = name
self.health = Player.max_health
def take_hit(self, damage):
self.health = max(0, self.health - damage)
return self.health == 0
def __str__(self):
return f"{self.name} ({self.health}/{Player.max_health})"
team = [Player("Ana"), Player("Ben")]
team[0].take_hit(30)
knocked_out = team[1].take_hit(120)
for p in team:
print(p)
print("Ben knocked out?", knocked_out)Ana (70/100)
Ben (0/100)
Ben knocked out? TrueLine-by-line explanation
- Line 2A class attribute shared by every player.
- Line 9max(0, ...) stops health from going below zero.
- Line 15Objects can be stored in a list like any other value.
A shopping basket made of objects
class Item:
def __init__(self, name, price, qty=1):
self.name = name
self.price = price
self.qty = qty
def total(self):
return self.price * self.qty
class Basket:
def __init__(self):
self.items = []
def add(self, item):
self.items.append(item)
def total(self):
return sum(item.total() for item in self.items)
basket = Basket()
basket.add(Item("Notebook", 3.50, 2))
basket.add(Item("Pen", 1.20, 5))
print(f"{len(basket.items)} lines, total £{basket.total():.2f}")2 lines, total £13.00Line-by-line explanation
- Lines 7 to 8Each item knows how to work out its own total.
- Line 12A basket object holds a list of item objects.
- Lines 17 to 18The basket's total asks each item for its total and adds them up.
Common Python Classes Mistakes
Forgetting self in a method definition
class Dog:
def bark():
return "Woof"
Dog().bark() # TypeError: bark() takes 0 positional arguments but 1 was givenclass Dog:
def bark(self):
return "Woof"Not storing values on self
class Dog:
def __init__(self, name):
name = name
print(Dog("Rex").name) # AttributeErrorclass Dog:
def __init__(self, name):
self.name = nameUsing a mutable class attribute for per-object data
class Basket:
items = [] # shared by every basket!
a, b = Basket(), Basket()
a.items.append("pen")
print(b.items) # ['pen']class Basket:
def __init__(self):
self.items = [] # each basket gets its own listPython Classes in Real Projects
Classes in real Python code
Web frameworks like Django describe database tables as classes, so a Product class becomes a products table and each object is one row. Games use classes for players, enemies and levels, and libraries such as datetime and pathlib give you objects with useful methods. Knowing how classes work makes all of these libraries much easier to understand.
Python Classes FAQ
What is the difference between a class and an object in Python?
A class is the definition: it describes what attributes and methods its objects will have. An object, also called an instance, is one concrete thing made from that class, with its own attribute values. Dog is the class; Dog("Rex", 3) creates an object.
What does self mean in Python?
self is the object the method was called on. When you write rex.bark(), Python passes rex as the first argument, so inside bark you reach its data through self.name. The name self is a strong convention rather than a keyword, but always use it.
Is __init__ a constructor?
In practice, yes: it is where you set up a new object's attributes. Strictly speaking, Python creates the empty object first with __new__ and then calls __init__ to initialise it. You will almost never need to write __new__ yourself.
What is the difference between __str__ and __repr__?
__str__ gives a friendly description for users and is used by print(). __repr__ gives an unambiguous description for developers, shown in the interactive shell and inside lists, ideally looking like code that recreates the object. If you only define one, define __repr__; Python falls back to it when __str__ is missing.
Does Python have private attributes?
Not enforced ones. A single leading underscore, _balance, marks an attribute as internal by convention. A double leading underscore, __balance, triggers name mangling, which makes accidental access from outside or from subclasses harder but still not impossible. Python relies on conventions rather than access modifiers like Java's private.
Python Classes Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the class so each object stores its title.
class Book:
def (self, title):
.title = title
What does this print?
class Cat:
def __init__(self, name):
self.name = name
a = Cat("Tom")
b = Cat("Kit")
print(b.name)
What does this print?
class Counter:
def __init__(self):
self.count = 0
def click(self):
self.count += 1
return self
c = Counter()
c.click().click().click()
print(c.count)
What is self in a method?
Which method controls what print(obj) shows?
Python Classes Quiz
5 questions to check what you learned.
How do you create an object from a class called
Car?- new Car()
- create Car
- Car.new()
- Car()
When does
__init__run?- Each time a new object is created
- When the program starts
- When the object is printed
- Only once per class
What is a class attribute?
- An attribute created inside __init__
- A private attribute
- An attribute defined in the class body, shared by all instances
- A method
What does a leading underscore in
_balancemean?- It's a syntax error
- By convention, it's internal and should be changed through methods
- Python makes it read-only
- It's a class attribute
Why is
items = []in a class body risky for per-object data?- Lists can't be attributes
- It slows the class down
- The same list is shared by every object of the class
- It deletes the list each time