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.

python
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.

python
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.48

Methods — Functions Inside Classes

Methods operate on object data. First parameter is always self (the instance).

python
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.

python
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.

python
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.

python
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.

python
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.

python
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.

python
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.

python
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.

python
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.