Lab 02 — Python Refresher¶
Session: Week 1 · Session 2 · 90 min CLO: CLO-1 Difficulty: Beginner
Learning objectives¶
By the end of this lab you can:
- Work fluently with lists, dicts, tuples, and sets.
- Write
forloops, conditionals, and list comprehensions. - Define and call functions with default arguments.
- Read a small data file and do simple summary math in pure Python.
Problem statement¶
You receive sales records as a plain-text file (one row per line,
product,units,price). Before anyone introduces pandas, the team wants a
pure-Python script that reads the file, computes totals per product, and
prints a clean report — so the logic is fully understood by hand.
Dataset requirements¶
Create sales.txt yourself with the starter code below (or type it by
hand). It is a small, hand-made dataset — 8 rows.
Step-by-step tasks¶
- Write a function
parse_line(line)that turns"coffee,3,2.50"into("coffee", 3, 2.5)— a tuple. - Write a function
read_sales(path)that reads the file, skips the header line, and returns a list of parsed tuples. Handle a blank line gracefully. - Write
totals_by_product(rows)returning a dictproduct -> total revenue(units × price). - Write
print_report(totals)that prints one line per product sorted by revenue (highest first) plus a grand total line. - Use a list comprehension somewhere in steps 1–4 and comment it.
- Run the full script; compare your output with the expected output.
Starter code¶
# sales.py
def parse_line(line):
"""'coffee,3,2.50' -> ('coffee', 3, 2.5). Return None for blank lines."""
line = line.strip()
if not line:
return None
# your code here: split on ',', convert types, return a tuple
def read_sales(path):
rows = []
with open(path) as f:
next(f) # skip header
for line in f:
row = parse_line(line)
if row is not None:
rows.append(row)
return rows
def totals_by_product(rows):
totals = {}
for product, units, price in rows:
# your code here: accumulate units * price per product
pass
return totals
def print_report(totals):
# your code here: sort by revenue descending, print, grand total
pass
if __name__ == "__main__":
rows = read_sales("sales.txt")
totals = totals_by_product(rows)
print_report(totals)
# sales.txt (create this file)
product,units,price
coffee,3,2.50
tea,5,1.20
coffee,2,2.50
cake,1,4.00
tea,2,1.20
juice,4,3.00
cake,2,4.00
coffee,1,2.50
Expected output¶
cake 12.00
juice 12.00
coffee 15.00
tea 8.40
grand total 47.40
(Sorting order: your choice between alphabetical and by revenue — say which you used in a comment.)
Questions¶
- What type does
parse_linereturn, and why is a tuple a good fit? - Why do we skip the first line of the file?
- What does
units * priceproduce ifunitsis a string? Why must you convert types? - Rewrite
totals_by_productwithdefaultdict— how does it change the code? - A customer buys
tea,0,1.20— what should the report show?
Challenge task¶
Extend the report with a max_product(totals) function that returns the
best-selling product by units (not revenue). Print it as
best by units: coffee. Then add a --sort alpha command-line flag
(sys.argv) that sorts the report alphabetically instead of by revenue.
Marking rubric¶
| Criteria | Max | Notes |
|---|---|---|
parse_line correct types & blank handling |
2 | returns tuple or None |
read_sales skips header, no errors |
2 | 8 rows parsed |
totals_by_product correct math |
3 | values match expected |
print_report sorted + grand total |
3 | formatting close to expected |
| Comprehension used & commented | 1 | anywhere in script |
| Answers to questions | 2 | Q2, Q3 correct |
Challenge: units max + --sort flag |
3 | both work |
| Total | 16 |