Exercise 10 of 10 · A complete program
The Cafe Ticket
What you will make
A printed cafe receipt with the shop name at the top, three item rows in straight columns, a subtotal, a service charge the program works out itself, a total, and a thank-you line at the bottom.
The one new idea: Assembling a complete program from parts you already know
Nothing in this program is new, and that is the point. Real software is almost never one clever idea; it is a handful of ordinary ones stacked in the order the work happens. Once you can look at a finished program and name the parts, you can read other people's code and keep building your own.
Go straight to the code ↓Nothing new, all at once
Every exercise so far handed you one new idea and somewhere small to try it. This one hands you no new idea at all. Every line in the editor is something you have already met.
That is what a finished program is. Not one clever trick, but a handful of ordinary ones arranged in the order the work actually happens. Here is this receipt, named piece by piece:
printputs each line on the screen. That was the very first thing you wrote.- Variables hold the parts that change:
name,qty,price. - Arithmetic turns them into amounts:
qty * pricefor one row,subtotal // 10for a tenth of the bill. - An
ifdecides whether the service charge applies to this order at all. - An f-string with widths —
{name:<12},{cost:>6}— is what makes the columns land in a straight line instead of wandering. - A list and a
forloop print the small notes at the bottom without a separateprintfor each one. - A running total collects the order as it goes, exactly as it collected the week of rainfall.
Seven ideas, none of them new here, all of them in one receipt.
The running total, one more time
subtotal = 0 sits above the items, and then subtotal = subtotal + cost appears once per item. It is the
same line you wrote for the rainfall, doing the same job on different values: work out the right-hand side
first, using whatever subtotal holds now, then store the answer back under the same name. The rainfall
chart had a loop repeat that line for it; here the three items sit one under the other, so it is repeated
by hand. The pattern does not mind either way.
It sits behind every bill, every score and every count you will write. A total is not typed. It is collected.
A worked example
A market stall rather than a cafe, so the receipt in the editor stays yours to finish:
total = 0
name = "Apples"
qty = 4
price = 12
cost = qty * price
total = total + cost
print(f"{name:<8}{cost:>5}")
name = "Bread"
qty = 1
price = 30
cost = qty * price
total = total + cost
print(f"{name:<8}{cost:>5}")
print("-------------")
print(f"TOTAL{total:>8}")Apples 48
Bread 30
-------------
TOTAL 78Two blocks of the same six lines with different values in them, and a total nobody typed in. Change the
4 to a 5 and both the apples row and the total move with it, because both are worked out rather than
written down.
Your turn
Press Run before changing anything. Most of the receipt is already correct: the header, the first two item rows, the service charge, the notes at the bottom.
Two lines are marked, and both of them already run. They are wrong, not missing.
- The cake's row still prints its four values with commas, so the numbers land nowhere near the columns above them. Rewrite it as an f-string matching the two rows above it. The widths you need are on those rows.
totalis set to0, so the bottom of the receipt disagrees with the rest of it. Work the total out from the two values the program already has: the amount for the items, and the service charge.
Then change something: the cake to two slices, the chai to another price. Run it again. The row, the subtotal, the service charge and the total should all move together. That is the difference between a receipt that is worked out and one that is typed.
If something goes wrong
The likeliest slip is the total, and it announces itself: the TOTAL line shows 0, or a number that does
not match the two above it. Check that both names on the right of the = are spelled as they are spelled
further up, and that the line still sits below the service charge — Python works down the page, so a value
has to exist before it can be added to anything.
If the cake row prints {name:<12} at you word for word, the f in front of the quote is missing. If it
prints but sits out of line, count the widths against the two rows above rather than guessing; one number
different is all it takes.
Nothing here can break. Change the order, run it again, and read your own receipt.
Write your code
Runs in your browser. Press Run (or Ctrl/Cmd+Enter) and the output is checked for you.
Press Esc then Tab to move keyboard focus out of the code editor.
Output will appear here after you run your code.The runtime is starting in the background. You can type now — it will be ready before you are.
The answer appears here once you have run your code at least once.
Things that often go wrong here
- Typing the final total in by hand
- The number is right this minute and wrong the moment anything changes. Order two slices of cake instead of one and the rows and the subtotal update themselves, while a typed total sits underneath contradicting them. A total is worked out from the values above it, never copied off the screen.
- Leaving the f off the front of the quote
- Without the f the curly braces are ordinary characters, so the cake row prints them back at you word for word instead of the values. No error appears, because a piece of text with braces in it is a perfectly legal thing to want.
- Giving the cake row different widths from the rows above it
- The rows line up only because every one of them gives the name twelve characters, the quantity three, the price five and the amount six. Change one of those numbers on one row and that row alone drifts out of column while the others stay put.
- Writing total = cost + service
- cost holds the amount for the last item only, because each block overwrites it with its own figure, so the receipt totals 69 instead of 154. The variable that has been collecting the whole order is subtotal.
Longer explanation: read the full lesson. Want a blank editor instead? Open the Python playground.