Produce the same formatted output three ways: with an f-string, with str.format and with percent-style formatting.
Python has three string formatting styles, and all three of them can produce exactly the same output. The difference between them is mostly about readability and about how the values reach the text.
name = 'Ada'
score = 99.456
print(f'{name} scored {score:.2f}')
print('{} scored {:.2f}'.format(name, score))
print('%s scored %.2f' % (name, score))
# An f-string can hold an expression and can pad the text to a width.
width = 8
print('|' + f'{name:>{width}}' + '|')
print(f'{3.14159:.2f}')
All three lines print the same sentence, with the score rounded to two decimal places. The format specifiers work in the same way in each style. The .2f part means two decimal places, and the letter f in front of the string is what marks it as an f-string.
The f-string version is the one to prefer in new code, and the reason is that the expression lives inside the braces right next to the text that uses it. An f-string can hold any expression, including a function call or an arithmetic operation, so you rarely need to prepare a separate variable first. The width example shows a nested replacement field. The outer braces hold a format spec, and the inner expression supplies the width, so you get eight characters of right-aligned text inside the pipes. The last line uses the same idea to ask for two decimal places.
Two details are worth knowing. The percent style is the oldest of the three and it comes from C, so its specifiers look different, such as %.2f instead of .2f, and the values must be given in a tuple unless you use a mapping. And str.format with named placeholders is still the right choice when the format string comes from somewhere else, such as a configuration file or a translation catalogue, because named fields can be reordered and can be filled in by a separate function.