Programs with f-strings
Three programs you have already written in an earlier chapter, printed the way somebody would actually want to read them. Nothing about the working changes — the arithmetic is the same, the loops are the same. Only the last few lines are different, and they are the ones the reader sees.
1Program 1 — a shop bill with GST
Ask for an item, its price and how many, then print a bill with the amount, 18% GST and the total payable — all lined up, all to two decimal places.
- the item name
- the price, as a
float - the quantity, as an
int
total = price * quantity- 18% of the total
- the two added together
- six lines, with the figures in a column
# a shop bill, from the user
item = input('Item name: ')
price = float(input('Price per unit: '))
quantity = int(input('How many? '))
total = price * quantity
gst = total * 18 / 100
payable = total + gst
print()
print(f'Item : {item}')
print(f'Rate : {price:10.2f}')
print(f'Quantity : {quantity:10}')
print(f'Amount : {total:10.2f}')
print(f'GST @18% : {gst:10.2f}')
print(f'Payable : {payable:10.2f}')Item name: Notebook Price per unit: 45.5 How many? 3 Item : Notebook Rate : 45.50 Quantity : 3 Amount : 136.50 GST @18% : 24.57 Payable : 161.07
print(f'Rate : {price:10.2f}')The labels are padded by hand with spaces so they are all the same length; the figures are padded by the width 10 so they end in the same column. Both halves matter — a column is only a column when both sides line up.
{quantity:10}A width but no decimals, because a quantity is a whole number. It still lands in the same column, because numbers pad to the right.
gst = total * 18 / 100Worked out in full and stored in full — 24.57 on screen is 24.57 exactly here, but on other numbers the stored value would carry more digits. The formatting is display only; the arithmetic never sees it.
45.5 is a perfectly good number and Rs 45.5 is not a perfectly good price. .2f is how you say “this is money” in output — and it is the reason every bill program in the projects chapter uses it.2Program 2 — a mark sheet with a heading row
Print a table of names and marks out of 150, with a percentage column and a heading row that lines up with the data underneath it.
# a mark sheet, out of 150, lined up
names = ['Asha', 'Ravindra', 'Meera', 'Karan']
marks = [128, 96, 141, 74]
out_of = 150
print(f'{"Name":12}{"Marks":>7}{"Percent":>10}')
for i in range(len(names)):
percent = marks[i] / out_of * 100
print(f'{names[i]:12}{marks[i]:7}{percent:10.1f}')
total = 0
for m in marks:
total = total + m
print()
print(f'Class average : {total / len(marks):.2f} out of {out_of}')
print(f'Class percent : {total / len(marks) / out_of * 100:.1f}%')Name Marks Percent Asha 128 85.3 Ravindra 96 64.0 Meera 141 94.0 Karan 74 49.3 Class average : 109.75 out of 150 Class percent : 73.2%
The headings are right-aligned with > because they sit over numbers, and numbers pad right. The name heading is not, because it sits over text. A heading should be aligned the way its column is, or the table looks broken even though every row is correct.
percent is made fresh on every round from marks[i], so nothing has to be kept in step. Storing a second parallel list of percentages would be one more thing that can drift out of line with the marks.3Program 3 — the multiplication table, lined up
Print a multiplication table where the numbers line up in columns however many digits they have.
# the multiplication table, lined up
num = int(input('Which table? '))
for i in range(1, 11):
print(f'{num:3} x {i:2} = {num * i:4}')Which table? 7 7 x 1 = 7 7 x 2 = 14 7 x 3 = 21 7 x 4 = 28 7 x 5 = 35 7 x 6 = 42 7 x 7 = 49 7 x 8 = 56 7 x 9 = 63 7 x 10 = 70
Look at the 10 in the second column and the two-digit answers in the third. Without the widths, the x and the = would shuffle left and right from row to row — the same table, and much harder to read. Widths of 3, 2 and 4 were chosen from the longest value each column can hold: a table up to 10 needs two characters for the counter and four for a product like 1000.
4Where this leaves the whole chapter
Dates, paths, comma lists. One print(), several values, a punctuation mark in the gaps.
Anything that has to stay on one line: tables, dots, patterns. Something afterwards supplies the newline.
A value inside a sentence, with no str() and no joining. And after a colon, how that value should be written.
+ and str(), or use commas and accept the spaces. Every program in the chapters after this one does, because they were written to work without this chapter. Read all three comfortably; write whichever the question asks for, and the f-string when it is your own program.- 1
Print a receipt for three items, each with a name, a quantity and a price, all in columns.
Hint · Three parallel lists and one loop, with the same widths in the heading row and the data row.
- 2
Print the temperature in Celsius and Fahrenheit to one decimal place, for 0 to 100 in steps of 10.
Hint ·
f = c * 9 / 5 + 32, and{c:6.1f}for both columns. - 3
Print a list of items and their prices with the total at the bottom, right-aligned in one column.
Hint · One width for the whole column, used on every line including the total.
- 4
Show the square and cube of 1 to 10 in three lined-up columns.
Hint · Widths chosen from the biggest value: 1000 needs four characters.
- 5
Print the time as
09:45:00from three separate numbers.Hint · This is the one
sepcould not do.{h:02}pads with zeros instead of spaces — try it and see.
Why do the heading row and the data row use the same widths?
In the bill program, gst holds a long decimal but prints as 24.57. What is stored?
Why is the Marks heading written as {'Marks':>7} rather than {'Marks':7}?