Object-Oriented Programming
Object-Oriented Programming (OOP) organizes code into reusable blueprints called classes. Business analysts use classes to model real entities—customers, products, orders—with their data and behaviors bundled together. OOP makes complex systems easier to understand, test, and extend.
Estimated reading time: 30–35 minutes
Core OOP Concepts
- Class → blueprint for creating objects
- Object → instance of a class with data
- __init__ → constructor, sets initial state
- Methods → functions that operate on object data
Great for: modeling business entities
Advanced Features
- Inheritance → reuse code from parent classes
- Encapsulation → hide internal details
- Properties → computed attributes with decorator
- __str__ / __repr__ → custom string representations
Great for: maintainable, extensible systems
Classes and Objects — The Basics
A class is a template. An object is a specific instance created from that template.
class Product:
def __init__(self, sku, name, price):
self.sku = sku
self.name = name
self.price = price
def discount(self, pct):
return self.price * (1 - pct)
# Create objects
widget = Product("SKU001", "Widget", 12.99)
gadget = Product("SKU002", "Gadget", 24.50)
print(widget.name) # "Widget"
print(widget.discount(0.1)) # 11.691 (10% off)The __init__ Constructor
__init__ runs when you create an object. Use it to set initial state.
class Order:
def __init__(self, order_id, customer, items):
self.order_id = order_id
self.customer = customer
self.items = items
self.status = "pending" # default value
def total(self):
return sum(item["price"] * item["qty"] for item in self.items)
order = Order("ORD123", "Ana", [
{"sku": "SKU001", "price": 12.99, "qty": 2},
{"sku": "SKU002", "price": 24.50, "qty": 1}
])
print(order.total()) # 50.48Methods — Functions Inside Classes
Methods operate on object data. First parameter is always self (the instance).
class SalesRep:
def __init__(self, name, region):
self.name = name
self.region = region
self.sales = []
def add_sale(self, amount):
self.sales.append(amount)
def total_sales(self):
return sum(self.sales)
def average_sale(self):
return self.total_sales() / len(self.sales) if self.sales else 0
rep = SalesRep("Ana", "North")
rep.add_sale(1200)
rep.add_sale(1500)
print(rep.name, ":", rep.total_sales(), "total")String Representations — __str__ and __repr__
Define how objects appear when printed or logged.
class Customer:
def __init__(self, id, name, email):
self.id = id
self.name = name
self.email = email
def __str__(self):
return self.name + " (" + self.email + ")"
def __repr__(self):
return "Customer(id=" + str(self.id) + ", name='" + self.name + "')"
customer = Customer(101, "Ana Garcia", "ana@company.com")
print(customer) # Ana Garcia (ana@company.com)
print(repr(customer)) # Customer(id=101, name='Ana Garcia')Properties — Computed Attributes
Use property decorator to create attributes that are calculated on demand.
class Invoice:
def __init__(self, subtotal, tax_rate=0.08):
self.subtotal = subtotal
self.tax_rate = tax_rate
@property
def tax(self):
return self.subtotal * self.tax_rate
@property
def total(self):
return self.subtotal + self.tax
inv = Invoice(100)
print("Subtotal:", inv.subtotal)
print("Tax:", round(inv.tax, 2))
print("Total:", round(inv.total, 2))Inheritance — Reusing Code
Child classes inherit attributes and methods from parent classes.
class Employee:
def __init__(self, name, id):
self.name = name
self.id = id
def display(self):
print("Employee:", self.name, "(ID:", self.id, ")")
class Manager(Employee):
def __init__(self, name, id, department):
super().__init__(name, id) # call parent constructor
self.department = department
def display(self):
super().display()
print("Department:", self.department)
mgr = Manager("Ana", 101, "Sales")
mgr.display()Cornerstone Project — Customer Account System (step-by-step)
Build a simple CRM system with Customer and Account classes. Track purchases, calculate lifetime value, flag VIP customers, and generate account summaries. This models real business logic you would use in analytics or automation.
Step 1 — Create Customer class
Model a customer with basic info and purchase history.
class Customer:
def __init__(self, id, name, email, tier="standard"):
self.id = id
self.name = name
self.email = email
self.tier = tier
self.purchases = []
def add_purchase(self, amount):
self.purchases.append(amount)
def lifetime_value(self):
return sum(self.purchases)
def __str__(self):
return self.name + " (" + self.tier + ")"
customer = Customer(101, "Ana Garcia", "ana@company.com")
customer.add_purchase(1200)
customer.add_purchase(1500)
print(customer, ": LTV $", customer.lifetime_value())Step 2 — Add VIP detection with property
Automatically flag customers who exceed a threshold.
class Customer:
VIP_THRESHOLD = 5000
def __init__(self, id, name, email):
self.id = id
self.name = name
self.email = email
self.purchases = []
def add_purchase(self, amount):
self.purchases.append(amount)
@property
def lifetime_value(self):
return sum(self.purchases)
@property
def is_vip(self):
return self.lifetime_value >= self.VIP_THRESHOLD
@property
def tier(self):
return "VIP" if self.is_vip else "Standard"
customer = Customer(101, "Ana", "ana@co.com")
customer.add_purchase(3000)
customer.add_purchase(2500)
print(customer.name, ":", customer.tier, "(LTV: $", customer.lifetime_value, ")")Step 3 — Create Account class with inheritance
Extend Customer with account-specific features like credit limit.
class Account(Customer):
def __init__(self, id, name, email, credit_limit=10000):
super().__init__(id, name, email)
self.credit_limit = credit_limit
@property
def available_credit(self):
return self.credit_limit - self.lifetime_value
def can_purchase(self, amount):
return self.lifetime_value + amount <= self.credit_limit
account = Account(201, "Bob Smith", "bob@co.com", credit_limit=5000)
account.add_purchase(2000)
print("Available credit: $", account.available_credit)
print("Can buy $4000?", account.can_purchase(4000))Step 4 — Generate account summary
Add a method that returns a formatted report.
class Account(Customer):
def __init__(self, id, name, email, credit_limit=10000):
super().__init__(id, name, email)
self.credit_limit = credit_limit
@property
def lifetime_value(self):
return sum(self.purchases)
@property
def available_credit(self):
return self.credit_limit - self.lifetime_value
@property
def tier(self):
return "VIP" if self.lifetime_value >= 5000 else "Standard"
def summary(self):
lines = []
lines.append("Account Summary")
lines.append("---------------")
lines.append("Name: " + self.name)
lines.append("Email: " + self.email)
lines.append("Tier: " + self.tier)
lines.append("Lifetime Value: $" + str(round(self.lifetime_value, 2)))
lines.append("Credit Limit: $" + str(round(self.credit_limit, 2)))
lines.append("Available: $" + str(round(self.available_credit, 2)))
lines.append("Purchases: " + str(len(self.purchases)))
return "\n".join(lines)
account = Account(201, "Bob", "bob@co.com")
account.add_purchase(2000)
account.add_purchase(1500)
print(account.summary())Step 5 — Manage multiple accounts
Create a simple CRM class to track all accounts.
class CRM:
def __init__(self):
self.accounts = {}
def add_account(self, account):
self.accounts[account.id] = account
def get_account(self, id):
return self.accounts.get(id)
def vip_accounts(self):
return [a for a in self.accounts.values() if a.tier == "VIP"]
def total_ltv(self):
return sum(a.lifetime_value for a in self.accounts.values())
# Use it
crm = CRM()
crm.add_account(Account(101, "Ana", "ana@co.com"))
crm.add_account(Account(102, "Bob", "bob@co.com"))
crm.get_account(101).add_purchase(6000) # makes Ana VIP
crm.get_account(102).add_purchase(2000)
print("VIP accounts:", len(crm.vip_accounts()))
print("Total LTV: $", round(crm.total_ltv(), 2))How this helps at work
- Organized code → customer logic lives in Customer class, easy to find
- Reusable → create hundreds of customer objects from one class
- Extensible → add new customer types (Enterprise, Partner) via inheritance
- Testable → test Customer class independently of database or UI
Key Takeaways
- Classes → blueprints for creating objects with data and behavior
- __init__ → constructor that sets initial state
- Methods → functions that operate on object data (self)
- Property decorator → computed attributes (lifetime_value, is_vip)
- Inheritance → reuse code by extending parent classes
- Cornerstone → CRM system models real business entities
Next Steps
You have mastered OOP basics. Next, explore modules and packages to organize classes into libraries, or dive into working with libraries to use powerful third-party classes like pandas DataFrames.