Classes and Objects
You’ve learned how to organize code with functions and modules. Now you’re ready for the next level: creating your own types. Classes let you bundle data and behavior together. Objects are instances of those classes. This is object-oriented programming, and it’s how Python models the real world.
In this tutorial, you’ll learn what classes and objects are, how to define them, and how to use them to write cleaner, more organized code.
Understanding Classes and Objects
Think of a class as a blueprint. A blueprint defines what a house will look like, but it’s not a house itself. You can build many houses from one blueprint. Each house is an object—an instance of the class.
In Python, strings are objects. Lists are objects. Even functions are objects. Every object belongs to a class that defines what it can do. When you write name.upper(), you’re calling a method that the str class defines.
You can create your own classes too. Let’s start with a simple one:
class Person:
pass
# Create an instance
alice = Person()
print(type(alice))
# <class '__main__.Person'>
The class keyword defines a new type. The variable alice holds an object—an instance of the Person class. Right now, this class doesn’t do much. Let’s add some data.
The Constructor: init
When you create an object, you often want to give it initial values. The __init__ method runs automatically when you create a new instance. It’s called the constructor:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
# Create two different people
alice = Person("Alice", 30)
bob = Person("Bob", 25)
print(alice.name) # Alice
print(bob.name) # Bob
The self parameter refers to the current instance being created. When you write self.name = name, you’re storing the name in that specific object. Each Person object has its own name and age.
This is the key insight: self lets each object keep its own data. Alice and Bob are separate instances, each with their own name and age.
Instance Attributes
Variables stored on an instance are called attributes. In the Person class, name and age are attributes. Every instance has these attributes, but the values differ:
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
# Two accounts, each with its own data
account1 = BankAccount("Alice", 1000)
account2 = BankAccount("Bob")
print(account1.owner) # Alice
print(account1.balance) # 1000
print(account2.owner) # Bob
print(account2.balance) # 0
The balance=0 parameter gives a default value. If you don’t provide a balance, it starts at zero.
Methods: Functions on Objects
Methods are functions defined inside a class. They operate on the instance they’re called on. Let’s add methods to our BankAccount:
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
if amount > 0:
self.balance += amount
return f"Deposited {amount}. New balance: {self.balance}"
return "Deposit amount must be positive"
def withdraw(self, amount):
if amount > self.balance:
return f"Insufficient funds. Balance: {self.balance}"
self.balance -= amount
return f"Withdrew {amount}. New balance: {self.balance}"
def __str__(self):
return f"Account for {self.owner}, balance: {self.balance}"
# Use the account
account = BankAccount("Alice", 500)
print(account)
# Account for Alice, balance: 500
print(account.deposit(200))
# Deposited 200. New balance: 700
print(account.withdraw(100))
# Withdrew 100. New balance: 600
Methods receive self automatically. When you call account.deposit(200), Python passes account as self and 200 as amount.
The __str__ method is special. Python calls it when you convert the object to a string, like with print(). It lets you control how your object displays.
A Complete Example: Product Inventory
Let’s build something more practical. This class manages products in an inventory:
class Product:
def __init__(self, name, price, quantity):
self.name = name
self.price = price
self.quantity = quantity
def total_value(self):
return self.price * self.quantity
def add_stock(self, amount):
if amount > 0:
self.quantity += amount
return f"Added {amount} to {self.name}. New quantity: {self.quantity}"
return "Amount must be positive"
def sell(self, amount):
if amount > self.quantity:
return f"Cannot sell {amount}. Only {self.quantity} in stock"
self.quantity -= amount
revenue = amount * self.price
return f"Sold {amount} for {revenue}. Remaining: {self.quantity}"
def __repr__(self):
return f"Product({self.name!r}, {self.price}, {self.quantity})"
# Create products
laptop = Product("Laptop", 999, 5)
phone = Product("Phone", 599, 10)
# Work with inventory
print(laptop.total_value())
# 4995
print(phone.sell(3))
# Sold 3 for 1797. Remaining: 7
print(laptop.add_stock(2))
# Added 2 to Laptop. New quantity: 7
This example shows the power of classes. The Product class bundles related data (name, price, quantity) with the operations that make sense on that data (calculating value, adding stock, selling). Everything stays together.
Key Concepts to Remember
The vocabulary matters. A class is the blueprint. An object (or instance) is a specific thing created from that blueprint. Attributes are variables stored on each instance. Methods are functions that operate on instances.
The __init__ method sets up new instances. The self parameter always refers to the current instance. Every method receives self as its first argument.
Classes let you create abstractions that match how you think about problems. A bank account has a balance and supports deposits and withdrawals. A product has a price and quantity. The class definition captures this relationship between data and behavior.
Next Steps
You now understand the basics of object-oriented programming in Python. Classes let you create custom types that bundle data with behavior.
The next tutorial in this series covers Reading and Writing Files — you’ll learn how to persist data, which pairs well with the classes you’ve learned to create here.