filter_active_clients from yesterday gives you only the clients worth invoicing. Now you need the total for each one. In your spreadsheet you drag the formula down six rows. What is the Python equivalent?
A loop? Go through each client, multiply rate by hours, store the result somewhere.
Exactly. for c in clients: iterates every dict in the list. c["rate"] * c["hours"] computes the total. enumerate() gives you the position so you can label each entry — useful for a numbered invoice run:
results = []
for i, c in enumerate(clients):
total = c["rate"] * c["hours"]
results.append({"name": c["name"], "total": total})
print(f"#{i+1} {c['name']}: ${total:.2f}")Why does enumerate give i+1? I'd expect it to start at 1 naturally.
enumerate starts at 0 by default — Python indices are zero-based. Add 1 when you want human-readable invoice numbers. Or pass start=1 to enumerate directly. Either works; the habit of enumerate(items, start=1) is cleaner for output.
And I can call format_invoice_line from Week 1 inside this loop to label each entry while I compute.
That is the pipeline working. Build the total, format the label, collect the results. Six clients, one loop, no dragging:
def compute_totals_per_client(clients: list) -> list:
results = []
for i, c in enumerate(clients, start=1):
total = c["rate"] * c["hours"]
results.append({"name": c["name"], "total": round(total, 2)})
print(f"Computed {len(results)} totals")
return resultsMy monthly formula-drag is now a loop that takes a millisecond.
One loop, six clients. Scale to sixty and the time stays the same.
enumerateenumerate() gives you both the index and the value in each iteration:
for i, client in enumerate(clients):
total = client['rate'] * client['hours']
result.append({'name': client['name'], 'total': total})Without enumerate, you'd use for client in clients and lose the index. With it, i is the position (0-based) and client is the dict.
Why build a new list? Each iteration appends a new dict {'name': ..., 'total': ...} — a leaner shape than the original. The result list grows by one entry per iteration.
rate * hours computes the invoice total: multiply the float fields and store the result in the new dict.
filter_active_clients from yesterday gives you only the clients worth invoicing. Now you need the total for each one. In your spreadsheet you drag the formula down six rows. What is the Python equivalent?
A loop? Go through each client, multiply rate by hours, store the result somewhere.
Exactly. for c in clients: iterates every dict in the list. c["rate"] * c["hours"] computes the total. enumerate() gives you the position so you can label each entry — useful for a numbered invoice run:
results = []
for i, c in enumerate(clients):
total = c["rate"] * c["hours"]
results.append({"name": c["name"], "total": total})
print(f"#{i+1} {c['name']}: ${total:.2f}")Why does enumerate give i+1? I'd expect it to start at 1 naturally.
enumerate starts at 0 by default — Python indices are zero-based. Add 1 when you want human-readable invoice numbers. Or pass start=1 to enumerate directly. Either works; the habit of enumerate(items, start=1) is cleaner for output.
And I can call format_invoice_line from Week 1 inside this loop to label each entry while I compute.
That is the pipeline working. Build the total, format the label, collect the results. Six clients, one loop, no dragging:
def compute_totals_per_client(clients: list) -> list:
results = []
for i, c in enumerate(clients, start=1):
total = c["rate"] * c["hours"]
results.append({"name": c["name"], "total": round(total, 2)})
print(f"Computed {len(results)} totals")
return resultsMy monthly formula-drag is now a loop that takes a millisecond.
One loop, six clients. Scale to sixty and the time stays the same.
enumerateenumerate() gives you both the index and the value in each iteration:
for i, client in enumerate(clients):
total = client['rate'] * client['hours']
result.append({'name': client['name'], 'total': total})Without enumerate, you'd use for client in clients and lose the index. With it, i is the position (0-based) and client is the dict.
Why build a new list? Each iteration appends a new dict {'name': ..., 'total': ...} — a leaner shape than the original. The result list grows by one entry per iteration.
rate * hours computes the invoice total: multiply the float fields and store the result in the new dict.
Sage needs a list of per-client totals to feed into the invoice formatter. Write `compute_totals_per_client(clients)` that iterates the client dicts, computes `rate * hours` for each, and returns a list of dicts with `name` and `total` (rounded to 2 decimal places). Each input dict has `name`, `rate`, and `hours` keys.
Tap each step for scaffolded hints.
No blank-editor panic.