Decimals & Widths
A placeholder can carry instructions as well as a value, after a colon — that second half has a name too, the format specification, though nobody says it out loud. There are a great many of them and you need two: .2f, which shows a number to two decimal places, and a width, which is what makes a column of output line up.
1.2f — for money, and for averages
Averages come out looking like this, and there is nothing wrong with them except that nobody wants to read one:
# rounding a number for display, without changing it
average = 74.66666666666667
print(average)
print(f'{average:.2f}')
print(f'{average:.1f}')
print(f'{average:.0f}')
print('and average is still', average)74.66666666666667 74.67 74.7 75 and average is still 74.66666666666667
{average:.2f}Read it as three parts: the value, a colon, then the instruction. .2f means 'as a decimal number, with 2 digits after the point'. The f here stands for float and has nothing to do with the f that starts the string.
{average:.0f}No digits after the point at all, so 74.666… shows as 75. It ROUNDS, it does not chop — which is the opposite of what int() would do.
print('and average is still', average)The last line is the point of the whole section: nothing was changed. The formatting decided how the value was WRITTEN this once, and the variable still holds every digit it had.
f'{x:.2f}' and round(x, 2): round() makes a new number that you might store and calculate with; an f-string just writes the one you have in a particular way. When the answer only needs to look tidy, format it — and keep the full value for the maths.2A width — the thing that makes a table
Put a plain number after the colon and it is a minimum width: the value is padded with spaces until it fills that many characters. That is all it takes to line a table up:
# lining a table up with a width
names = ['Asha', 'Ravindra', 'Meera']
marks = [72, 65, 88]
for i in range(len(names)):
print(f'{names[i]:10} {marks[i]:5}')
print()
for i in range(len(names)):
print(f'{names[i]:<10}|{marks[i]:>5}')Asha 72 Ravindra 65 Meera 88 Asha | 72 Ravindra | 65 Meera | 88
< and >, so you can see the rule and override it.{x:<10}Pad on the right. The default for text.
{x:>10}Pad on the left. The default for numbers.
{x:^10}Pad on both sides, as evenly as it can.
3Both together: a bill
A width and a number of decimals go in the same instruction, width first: {total:8.2f} means “two decimal places, in a column eight characters wide”.
# a bill, printed properly
item = 'Notebook'
price = 45.5
quantity = 3
total = price * quantity
print(f'{item:12} {quantity:3} x {price:7.2f} = {total:8.2f}')
print(f'Total payable: Rs {total:.2f}')Notebook 3 x 45.50 = 136.50 Total payable: Rs 136.50
45.5 printed as 45.50 — the second decimal place is there because money has two, not because the number does. That is a display decision, and it is exactly the kind of thing formatting is for.
4How much of this to learn
f'{x:.2f}' 74.67 two decimal places
f'{x:.0f}' 75 none — and it rounds
f'{name:10}' 'Asha ' at least 10 wide, text goes left
f'{n:5}' ' 72' at least 5 wide, numbers go right
f'{x:<10}' left force it left
f'{x:>10}' right force it right
f'{x:^10}' centre force it centre
f'{x:8.2f}' ' 136.50' a width AND two decimals5Recap
{value:instruction}. The value is worked out first, exactly as before; the instruction only decides how it is written.
74.666… shows as 74.67 and the variable still holds every digit. round() makes a new number; formatting does not.
Text pads to the left of it, numbers to the right — the defaults you want. < > ^ override them.
Decimal places and widths answer nearly every Class 11 question. The rest of the format language can wait.
average holds 74.66666666666667. After print(f'{average:.2f}'), what does average hold?
A name is 14 characters long and the format says {name:10}. What happens?
What does f'{45.5:7.2f}' produce?