Chapter 6 — Strings, Files, and Object-Oriented Programming

Real data arrives as text and files. This chapter deepens string handling and regular expressions, covers file I/O and exception handling, then introduces object-oriented programming — the paradigm behind the pandas and scikit-learn objects you will use throughout the book.

Learning Objectives

Prerequisites / Imports

Uses the standard re and csv modules.

In [1]:
import re
import csv
import os

1 The str Class

Strings are immutable; methods return new strings. Common tools: strip, split, join, replace, find, count, upper/lower.

In [1]:
raw = '  Data Science, 2026  '
clean = raw.strip()
print('stripped:', repr(clean))
print('upper:', clean.upper())
print('words:', clean.split())
print('joined:', '-'.join(clean.split()))
print('replace:', clean.replace('Science', 'Engineering'))
stripped: 'Data Science, 2026'
upper: DATA SCIENCE, 2026
words: ['Data', 'Science,', '2026']
joined: Data-Science,-2026
replace: Data Engineering, 2026

2 Regular Expressions for Data Cleaning

re finds and substitutes patterns — essential for messy text.

In [1]:
text = 'Call 555-1234 or 555.5678 for help'
phones = re.findall(r'\d{3}[-.]\d{4}', text)
print('phones found:', phones)

cleaned = re.sub(r'[^a-zA-Z0-9 ]', '', 'Price: $19.99! #deal')
print('cleaned:', cleaned)
phones found: ['555-1234', '555.5678']
cleaned: Price 1999 deal

3 Files: Reading and Writing

Use with open(...) so files close automatically. We write and read a small CSV.

In [1]:
path = 'ch06_sales.csv'
with open(path, 'w', newline='') as f:
    w = csv.writer(f)
    w.writerow(['item', 'qty', 'price'])
    w.writerows([('Widget', 3, 4.50), ('Gadget', 2, 12.75), ('Cable', 5, 1.20)])

with open(path, 'r') as f:
    for row in csv.DictReader(f):
        print(row)
{'item': 'Widget', 'qty': '3', 'price': '4.5'}
{'item': 'Gadget', 'qty': '2', 'price': '12.75'}
{'item': 'Cable', 'qty': '5', 'price': '1.2'}

4 Exception Handling

Catch errors to keep programs robust. try/except/else/finally.

In [1]:
try:
    with open('does_not_exist.csv') as f:
        data = f.read()
except FileNotFoundError:
    print('File not found — handled gracefully.')
finally:
    print('Cleanup runs no matter what.')
File not found — handled gracefully.
Cleanup runs no matter what.
In [1]:
def safe_divide(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return float('inf')

print(safe_divide(10, 0))
inf

5 Defining Classes

A class bundles data (attributes) and behavior (methods). __init__ is the constructor; self refers to the instance.

In [1]:
class Student:
    def __init__(self, name, scores):
        self.name = name
        self.scores = scores

    def average(self):
        return sum(self.scores) / len(self.scores)

    def __str__(self):
        return f'Student({self.name}, avg={self.average():.1f})'

s = Student('Ada', [88, 92, 79])
print(s)
print('average:', s.average())
Student(Ada, avg=86.3)
average: 86.33333333333333

6 Special Methods and Operator Overloading

Dunder methods customize object behavior, e.g. __eq__ for ==.

In [1]:
class Money:
    def __init__(self, dollars, cents=0):
        self.total_cents = dollars * 100 + cents

    def __eq__(self, other):
        return self.total_cents == other.total_cents

    def __add__(self, other):
        return Money(0, self.total_cents + other.total_cents)

    def __str__(self):
        return f'${self.total_cents/100:.2f}'

print(Money(5, 50) + Money(2, 75))
print(Money(1, 0) == Money(0, 100))
$8.25
True

7 Encapsulation

Prefix attributes with _ to signal "internal". Provide methods to control access.

In [1]:
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 += amount

    def withdraw(self, amount):
        if amount > self._balance:
            raise ValueError('Insufficient funds')
        self._balance -= amount

    @property
    def balance(self):
        return self._balance

acc = Account('Bo', 100)
acc.deposit(50)
acc.withdraw(30)
print('balance:', acc.balance)
balance: 120

8 OOP Underpins the Data-Science Stack

A pandas DataFrame is an object with methods (head, describe, groupby). A scikit-learn estimator is an object with fit and predict. Understanding classes helps you read documentation and extend these tools.

In [1]:
# Preview: a DataFrame is an object with methods
import pandas as pd
df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]})
print(type(df))
print('methods include:', [m for m in ['head','describe','groupby','sum'] if hasattr(df, m)])
df.sum()
<class 'pandas.core.frame.DataFrame'>
methods include: ['head', 'describe', 'groupby', 'sum']
x     6
y    15
dtype: int64

Case Study: A Customer Record Class with File Persistence

Define a Customer class, create instances, persist them to CSV, read them back, and handle a missing file gracefully.

In [1]:
class Customer:
    def __init__(self, cid, name, email, balance=0.0):
        self.cid = cid
        self.name = name
        self.email = email
        self.balance = balance

    def apply_transaction(self, amount):
        self.balance += amount
        return self.balance

    def __str__(self):
        return f'{self.cid}|{self.name}|{self.email}|{self.balance:.2f}'

customers = [
    Customer(1, 'Ada Lovelace', 'ada@example.com', 500),
    Customer(2, 'Bo Yang', 'bo@example.com', 320),
    Customer(3, 'Cy Patel', 'cy@example.com', -50),
]

# Persist to CSV
path = 'ch06_customers.csv'
with open(path, 'w', newline='') as f:
    w = csv.writer(f)
    w.writerow(['id', 'name', 'email', 'balance'])
    for c in customers:
        w.writerow([c.cid, c.name, c.email, c.balance])
print('Saved', path)

# Read back into Customer objects
loaded = []
try:
    with open(path, 'r') as f:
        for row in csv.DictReader(f):
            loaded.append(Customer(int(row['id']), row['name'], row['email'], float(row['balance'])))
except FileNotFoundError:
    print('No customer file found.')

for c in loaded:
    print(c)
Saved ch06_customers.csv
1|Ada Lovelace|ada@example.com|500.00
2|Bo Yang|bo@example.com|320.00
3|Cy Patel|cy@example.com|-50.00

Exercises

  1. Strip whitespace and title-case the string ' data science '.
  2. Use re.findall to extract all numbers from 'order 3 of 14 items, total 99'.
  3. Write a list of dicts to a CSV file and read it back.
  4. Write a try/except that catches a ValueError from int('abc').
  5. Add a grade() method to the Student class that returns a letter grade.
  6. Implement __eq__ on a Point class comparing x and y.
  7. Add validation to Account.withdraw and test it raises on overdraft.
  8. Explain the difference between self._balance and self.balance.
  9. Write a function that counts words in a text file.
  10. Describe two ways pandas/scikit-learn objects use OOP.

Python Data Science: From Foundations to Applications — Chapter 6