Widths and alignment
Values of different lengths make ragged output. A table is easier to read when each column has its own width. In a format specifier, a number on its own is a width: the value takes at least that many characters, and spaces fill the rest:
fruit = ["fig", "banana", "kiwi"]
prices = [3, 12, 5]
for i in range(len(fruit)):
print(f"{fruit[i]:8}|{prices[i]:4}|")
fig | 3|
banana | 12|
kiwi | 5|The names take 8 characters and the prices 4. Strings are put at the left edge of their space, numbers at the right. That's the usual way: words line up at their start and numbers at their last digit.
Choosing the alignment
A character before the width chooses the alignment: < for the left, > for the right and ^ for the middle:
word = "cat"
print(f"[{word:<7}]")
print(f"[{word:>7}]")
print(f"[{word:^7}]")
[cat ]
[ cat]
[ cat ]A width is the least space a value takes, not the most. A longer value isn't cut: {"elephant":4} is the whole elephant, and the column after it shifts. Choose widths for the longest value you expect.
Width and decimals together
For numbers with decimals, the width comes before the dot. {price:7.2f} shows the price with two decimals, in a space of 7 characters. That's what lines up the decimal points of a receipt:
items = ["Coffee", "Croissant", "Water"]
prices = [3.5, 2.95, 1.2]
for i in range(len(items)):
print(f"{items[i]:<12}{prices[i]:7.2f}")
print("-" * 19)
print(f"{'Total':<12}{sum(prices):7.2f}")
Coffee 3.50
Croissant 2.95
Water 1.20
-------------------
Total 7.65The two widths add up to 19, the length of the dashed line. Inside an f-string in double quotes, a string in the braces is written in single quotes, like 'Total'.