Lesson 03 · foundations

Strings, Slicing & File I/O

The last stop before pandas.read_csv stops looking like magic.

Every dataset starts life as a file on disk — usually a .csv of raw text. Before pandas does the heavy lifting, you should know what it's doing underneath: opening a file, reading text, and splitting it into fields. That's this lesson.

1. Strings are sequences too

A string indexes and slices exactly like a list — because it is a sequence, just an immutable one of characters.

ticker = "AAPL"

first = ticker[0]      # "A"
last  = ticker[-1]     # "L"
sub   = ticker[1:3]    # "AP"  (same start:stop rules as lists)

Common string methods you'll use constantly on real data:

row = "  AAPL, 150.25, 1200000  "

row.strip()             # "AAPL, 150.25, 1200000"  — drop leading/trailing whitespace
row.strip().split(",")  # ["AAPL", " 150.25", " 1200000"] — split into a list
"-".join(["A", "B"])    # "A-B" — the reverse of split

"aapl".upper()          # "AAPL"
"AAPL".lower()           # "aapl"
"AAPL".startswith("A")  # True
Note .split(",") on a raw line is literally what a CSV parser does per row, before pandas or the csv module handle the edge cases (quoted commas, embedded newlines) for you.

2. Opening a file: with open(...)

Files are opened with open() and should always be wrapped in a with block — it closes the file automatically, even if an error happens partway through.

with open("prices.csv") as f:
    contents = f.read()      # whole file as one string

# or, line by line (the common case):
with open("prices.csv") as f:
    for line in f:
        print(line.strip())  # strip() drops the trailing newline
Why with, not manual open/close Without with, you'd need f = open(...) then remember f.close() — and forget it the moment an exception fires. with is Python's context manager pattern: it guarantees cleanup on the way out, no matter how the block exits.

3. Parsing CSV properly: the csv module

.split(",") breaks the moment a field contains a comma inside quotes (e.g. "Smith, John"). The standard library's csv module handles that correctly — use it instead of hand-rolled splitting for anything real:

import csv

with open("prices.csv") as f:
    reader = csv.DictReader(f)   # first row becomes field names automatically
    for row in reader:
        print(row["ticker"], row["price"])
        # row is a dict: {"ticker": "AAPL", "price": "150.25", ...}
Note Every value csv.DictReader gives you is a string"150.25", not 150.25. You convert types yourself (float(row["price"])). This is exactly the "wrong types" cleanup step the mission calls out — pandas' read_csv does this type-guessing for you, which is why it exists.

Do this now

Create a small CSV and parse it back out:

  1. Save a file trades.csv with this content:
    ticker,shares,price
    AAPL,10,150.25
    MSFT,5,310.00
    GOOG,2,2800.50
  2. Write a script that opens it with csv.DictReader.
  3. For each row, convert shares and price to numbers and print the total value of that row (shares × price).
  4. Sum all rows and print the grand total.
Stuck? View a solution
import csv

total = 0
with open("trades.csv") as f:
    reader = csv.DictReader(f)
    for row in reader:
        shares = int(row["shares"])
        price = float(row["price"])
        value = shares * price
        print(f"{row['ticker']}: ${value:,.2f}")
        total += value

print(f"Total: ${total:,.2f}")
Win You can now read a real file off disk, parse each row, and convert raw text into usable numbers — the exact steps pandas.read_csv automates. Next lesson: pandas itself, starting with loading this same CSV into a DataFrame in one line and seeing what it gives you for free.

Go deeper