Skip to content

Basics of Classes

Learn the fundamentals of creating and using classes in Python.

Before diving into advanced OOP concepts, let’s start with the fundamentals: understanding what classes are and how to write them in Python.

A class is a blueprint or template for creating objects. It defines:

  • Attributes (data/variables)
  • Methods (functions that operate on the data)

An object (or instance) is a specific realization of a class - a concrete example created from the blueprint.

Think of a class like a cookie cutter:

  • The class is the cookie cutter (the template)
  • The objects are the cookies (specific instances created from the template)

All cookies made from the same cutter have the same shape, but each cookie is a separate object.

Here’s the simplest class definition:

simple_class.py
class Dog:
pass # Empty class
# Create an instance (object)
my_dog = Dog()
print(type(my_dog)) # <class '__main__.Dog'>
Output
<class '__main__.Dog'>

The __init__ method is a special method called a constructor. It’s automatically called when you create a new instance of a class.

init_method.py
class Dog:
def __init__(self, name: str, breed: str):
"""Constructor - called when creating a new Dog instance"""
self.name = name
self.breed = breed
# Create instances
dog1 = Dog("Buddy", "Golden Retriever")
dog2 = Dog("Max", "German Shepherd")
print(dog1.name) # "Buddy"
print(dog2.breed) # "German Shepherd"
Output
Buddy
German Shepherd

self refers to the current instance of the class. It’s the first parameter of instance methods (though you don’t pass it explicitly when calling the method).

understanding_self.py
class Person:
def __init__(self, name: str, age: int):
# self refers to the current instance
self.name = name # Instance attribute
self.age = age # Instance attribute
def introduce(self):
# self allows access to instance attributes
return f"Hi, I'm {self.name} and I'm {self.age} years old"
person = Person("Alice", 30)
print(person.introduce()) # "Hi, I'm Alice and I'm 30 years old"
Output
Hi, I'm Alice and I'm 30 years old

Instance attributes are variables that belong to a specific instance. Each object has its own copy of these attributes.

instance_attributes.py
class BankAccount:
def __init__(self, account_number: str, balance: float):
# Instance attributes - unique to each account
self.account_number = account_number
self.balance = balance
# Each account has its own balance
account1 = BankAccount("ACC-001", 1000.0)
account2 = BankAccount("ACC-002", 500.0)
print(account1.balance) # 1000.0
print(account2.balance) # 500.0
Output
1000.0
500.0

Instance methods are functions defined inside a class that operate on instance data. They always take self as the first parameter.

instance_methods.py
class BankAccount:
def __init__(self, account_number: str, balance: float):
self.account_number = account_number
self.balance = balance
def deposit(self, amount: float):
"""Instance method - operates on this account"""
if amount > 0:
self.balance += amount
return f"Deposited ${amount:.2f}. New balance: ${self.balance:.2f}"
return "Invalid deposit amount"
def withdraw(self, amount: float):
"""Instance method - operates on this account"""
if 0 < amount <= self.balance:
self.balance -= amount
return f"Withdrew ${amount:.2f}. New balance: ${self.balance:.2f}"
return "Insufficient funds or invalid amount"
def get_balance(self):
"""Instance method - returns this account's balance"""
return self.balance
# Usage
account = BankAccount("ACC-001", 1000.0)
print(account.deposit(500.0)) # Deposited $500.00. New balance: $1500.00
print(account.withdraw(200.0)) # Withdrew $200.00. New balance: $1300.00
print(account.get_balance()) # 1300.0
Output
Deposited $500.00. New balance: $1500.00
Withdrew $200.00. New balance: $1300.00
1300.0

Let’s put it all together with a complete example:

user_class.py
class User:
"""A simple User class demonstrating basic OOP concepts"""
def __init__(self, username: str, email: str, age: int):
"""Constructor - initialize user attributes"""
self.username = username
self.email = email
self.age = age
self.is_active = True # Default value
def get_info(self):
"""Instance method - return user information"""
status = "active" if self.is_active else "inactive"
return f"User: {self.username} ({self.email}), Age: {self.age}, Status: {status}"
def deactivate(self):
"""Instance method - deactivate user account"""
self.is_active = False
return f"{self.username} has been deactivated"
def activate(self):
"""Instance method - activate user account"""
self.is_active = True
return f"{self.username} has been activated"
def update_email(self, new_email: str):
"""Instance method - update user email"""
if "@" in new_email:
self.email = new_email
return f"Email updated to {new_email}"
return "Invalid email address"
# Create user instances
user1 = User("alice", "alice@example.com", 25)
user2 = User("bob", "bob@example.com", 30)
# Each user is independent
print(user1.get_info())
print(user2.get_info())
# Modify one user - doesn't affect the other
user1.deactivate()
print(user1.get_info())
print(user2.get_info())
Output
User: alice (alice@example.com), Age: 25, Status: active
User: bob (bob@example.com), Age: 30, Status: active
User: alice (alice@example.com), Age: 25, Status: inactive
User: bob (bob@example.com), Age: 30, Status: active
classDiagram
    class User {
        -username: str
        -email: str
        -age: int
        -is_active: bool
        +__init__(username, email, age)
        +get_info() str
        +deactivate() str
        +activate() str
        +update_email(new_email) str
    }
    
    note for User "Class: Blueprint\nInstance: Specific user"
product_class.py
class Product:
"""Product class for an e-commerce system"""
def __init__(self, name: str, price: float, sku: str):
"""Initialize product with name, price, and SKU"""
self.name = name
self.price = price
self.sku = sku
self.stock = 0 # Default stock level
def add_stock(self, quantity: int):
"""Add items to stock"""
if quantity > 0:
self.stock += quantity
return f"Added {quantity} units. Stock: {self.stock}"
return "Invalid quantity"
def sell(self, quantity: int):
"""Sell items from stock"""
if quantity <= 0:
return "Invalid quantity"
if quantity > self.stock:
return f"Insufficient stock. Available: {self.stock}"
self.stock -= quantity
return f"Sold {quantity} units. Remaining stock: {self.stock}"
def get_total_value(self):
"""Calculate total value of current stock"""
return self.stock * self.price
def display_info(self):
"""Display product information"""
return f"{self.name} (SKU: {self.sku}) - ${self.price:.2f} | Stock: {self.stock}"
# Usage
laptop = Product("Laptop", 999.99, "LAP-001")
mouse = Product("Mouse", 29.99, "MOU-001")
# Each product is independent
laptop.add_stock(10)
mouse.add_stock(50)
print(laptop.display_info())
print(mouse.display_info())
laptop.sell(3)
print(laptop.get_total_value()) # 6999.93 (7 laptops * $999.99)
Output
Added 10 units. Stock: 10
Added 50 units. Stock: 50
Laptop (SKU: LAP-001) - $999.99 | Stock: 10
Mouse (SKU: MOU-001) - $29.99 | Stock: 50
Sold 3 units. Remaining stock: 7
6999.93
## Key Concepts Summary
### 1. Class Definition
```python
class ClassName:
# Class body
pass
def __init__(self, param1, param2):
self.attribute1 = param1
self.attribute2 = param2
def method_name(self, param1, param2):
# Method body
# Access instance attributes with self.attribute
return result
instance = ClassName(arg1, arg2)
instance.attribute # Access attribute
instance.method() # Call method
defaults_pattern.py
class User:
def __init__(self, username: str, email: str, age: int = 18):
"""Age has a default value"""
self.username = username
self.email = email
self.age = age
user1 = User("alice", "alice@example.com") # Uses default age
user2 = User("bob", "bob@example.com", 25) # Overrides default age

Pattern 2: Methods That Return Information

Section titled “Pattern 2: Methods That Return Information”
info_methods.py
class Rectangle:
def __init__(self, width: float, height: float):
self.width = width
self.height = height
def area(self):
"""Calculate and return area"""
return self.width * self.height
def perimeter(self):
"""Calculate and return perimeter"""
return 2 * (self.width + self.height)
rect = Rectangle(5, 3)
print(rect.area()) # 15
print(rect.perimeter()) # 16
Output
15
16
state_modification.py
class Counter:
def __init__(self, initial_value: int = 0):
self.value = initial_value
def increment(self):
"""Modify the counter value"""
self.value += 1
def decrement(self):
"""Modify the counter value"""
self.value -= 1
def reset(self):
"""Reset to zero"""
self.value = 0
counter = Counter(10)
counter.increment()
print(counter.value) # 11
counter.decrement()
print(counter.value) # 10
counter.reset()
print(counter.value) # 0
Output
11
10
0
Diagram

Now that you understand the basics of classes, you’re ready to explore:

  • Encapsulation - Protecting data with access modifiers
  • Inheritance - Creating class hierarchies
  • Polymorphism - Using objects interchangeably
  • Advanced features - Properties, static methods, and more

Remember: Classes are a way to model real-world entities in code, bundling together related data (attributes) and behavior (methods) into a single, reusable unit.