Every month you build the same invoice for six clients. You change the name, the hours, the total. What if you wrote that formula once, named it, and documented it so you could hand it to an assistant?
Like a template I fill in? But one that does the maths automatically and tells the next person what to pass?
Closer than you think. def make_invoice_line(name, stats, rank): is your template name. The docstring is the explanation. stats is the dict from status_summary — {"total_hours": 4.5, "total_revenue": 540.0, "avg_rate": 120.0} — so the function computes from pre-aggregated data:
def make_invoice_line(name: str, stats: dict, rank: int) -> str:
"""Format a ranked invoice line from a client stats dict."""
hours = stats.get("total_hours", 0)
revenue = stats.get("total_revenue", 0.0)
rate = stats.get("avg_rate", 0.0)
return f"#{rank} {name} — Hours: {hours:.1f} | Rate: ${rate:.2f}/hr | Total: ${revenue:.2f}"What is the point of the docstring if Python does not use it? I thought it was just a comment.
Python does use it — help(make_invoice_line) prints it in the console. Your future self and your assistant will thank you. A function without a docstring is a black box. A function with one is a labelled invoice template.
And rank feeds into the numbered invoice format — #1 Acme, #2 Brand. I can loop over the sorted client list and pass the index.
That is Week 4 — you are already planning ahead. One function, all six invoice lines, zero re-typing:
def make_invoice_line(name: str, stats: dict, rank: int) -> str:
"""Format a ranked invoice line from a client stats dict."""
hours = stats.get("total_hours", 0)
revenue = stats.get("total_revenue", 0.0)
rate = stats.get("avg_rate", 0.0)
result = f"#{rank} {name} — Hours: {hours:.1f} | Rate: ${rate:.2f}/hr | Total: ${revenue:.2f}"
print(f"Invoice line: {result}")
return resultI just automated my Monday invoice run in eight lines.
And that is just one client field. What happens when you add tax in Week 4?
A function definition has four parts:
def make_invoice_line(name: str, stats: dict, rank: int) -> str:
"""Format a ranked invoice line from a client stats dict."""
# body
return resultdef — keywordname: str, stats: dict, rank: intreturn — the value passed back to the callerHints are documentation, not enforcement. Python runs the function even if you pass the wrong type. They help editors, linters, and future readers.
Every month you build the same invoice for six clients. You change the name, the hours, the total. What if you wrote that formula once, named it, and documented it so you could hand it to an assistant?
Like a template I fill in? But one that does the maths automatically and tells the next person what to pass?
Closer than you think. def make_invoice_line(name, stats, rank): is your template name. The docstring is the explanation. stats is the dict from status_summary — {"total_hours": 4.5, "total_revenue": 540.0, "avg_rate": 120.0} — so the function computes from pre-aggregated data:
def make_invoice_line(name: str, stats: dict, rank: int) -> str:
"""Format a ranked invoice line from a client stats dict."""
hours = stats.get("total_hours", 0)
revenue = stats.get("total_revenue", 0.0)
rate = stats.get("avg_rate", 0.0)
return f"#{rank} {name} — Hours: {hours:.1f} | Rate: ${rate:.2f}/hr | Total: ${revenue:.2f}"What is the point of the docstring if Python does not use it? I thought it was just a comment.
Python does use it — help(make_invoice_line) prints it in the console. Your future self and your assistant will thank you. A function without a docstring is a black box. A function with one is a labelled invoice template.
And rank feeds into the numbered invoice format — #1 Acme, #2 Brand. I can loop over the sorted client list and pass the index.
That is Week 4 — you are already planning ahead. One function, all six invoice lines, zero re-typing:
def make_invoice_line(name: str, stats: dict, rank: int) -> str:
"""Format a ranked invoice line from a client stats dict."""
hours = stats.get("total_hours", 0)
revenue = stats.get("total_revenue", 0.0)
rate = stats.get("avg_rate", 0.0)
result = f"#{rank} {name} — Hours: {hours:.1f} | Rate: ${rate:.2f}/hr | Total: ${revenue:.2f}"
print(f"Invoice line: {result}")
return resultI just automated my Monday invoice run in eight lines.
And that is just one client field. What happens when you add tax in Week 4?
A function definition has four parts:
def make_invoice_line(name: str, stats: dict, rank: int) -> str:
"""Format a ranked invoice line from a client stats dict."""
# body
return resultdef — keywordname: str, stats: dict, rank: intreturn — the value passed back to the callerHints are documentation, not enforcement. Python runs the function even if you pass the wrong type. They help editors, linters, and future readers.
Nina needs a reusable, documented function to format each client's invoice line for the monthly report. Write `make_invoice_line(name, stats, rank)` that takes a client name, a stats dict with `total_hours`, `total_revenue`, and `avg_rate` keys, and a rank integer, then returns a formatted string like `"#1 Acme Corp — Hours: 4.5 | Rate: $120.00/hr | Total: $540.00"`.
Tap each step for scaffolded hints.
No blank-editor panic.