What an f-string Is
Putting a value inside a sentence has cost you something on every page so far — either commas that force a space you may not want, or + with str() wrapped round every number. An f-string is the third way: write the sentence, and put the value in it, in braces.
1The same line, three ways
# the same line, three ways
name = 'Asha'
marks = 91
print('Name:', name, 'Marks:', marks)
print('Name: ' + name + ' Marks: ' + str(marks))
print(f'Name: {name} Marks: {marks}')Name: Asha Marks: 91 Name: Asha Marks: 91 Name: Asha Marks: 91
| way | what it costs you |
|---|---|
| commas | A space appears between every argument whether you want one or not. Nothing to convert, nothing to break. |
| + and str() | Total control of the spacing, and a str() round every number — miss one and it is a TypeError. |
| f-string | Total control of the spacing, no str() anywhere, and the sentence reads as the sentence it will print. |
2The two parts: the f, and the braces
print(f'Name: {name} Marks: {marks}')
| | |
| | +-- a PLACEHOLDER: the braces and what is in them,
| | replaced by the value when the string is used
| +------- ordinary text, printed exactly as written
+--------------- the f, immediately before the quote{...} is replaced by whatever it holds. Two names, one thing; recognise both and use whichever the question uses.f, the braces are just characters. Python does not look inside '{name}' at all — it prints the braces and the word. The f is what turns an ordinary string into one that gets read for braces before it is used, and it goes immediately before the opening quote, with no space.# the f is not optional, and neither are the braces
name = 'Asha'
print(f'Hello {name}')
print('Hello {name}')
print(f'Hello name')Hello Asha
Hello {name}
Hello nameThree lines, three different mistakes to recognise. The second forgot the f, so nothing was replaced and the braces printed themselves. The third had the f but no braces, so name was just a word in a sentence. Neither is an error — both print something, and that is what makes them worth meeting on purpose.
3Anything that has a value can go in the braces
Not only names. Whatever is between the braces is worked out first, exactly as if it had been written on its own line, and the answer is dropped into the sentence:
# what goes inside the braces is worked out first
a = 7
b = 3
print(f'{a} + {b} = {a + b}')
print(f'{a} // {b} = {a // b}')
print(f'{a} is bigger than {b}: {a > b}')
word = 'python'
print(f'{word} has {len(word)} letters and starts with {word[0]}')7 + 3 = 10 7 // 3 = 2 7 is bigger than 3: True python has 6 letters and starts with p
f'{a} + {b} = {a + b}'Three braces. The first two hold names; the third holds a whole expression, worked out on the spot. The + between the first two braces is ordinary text — it is outside the braces, so nothing is added.
f'... {a > b}'A comparison has a value too, so it can go in a brace. It prints True or False with a capital letter, because that is how Python writes them.
f'{word} has {len(word)} letters'A function call inside a brace. Anything you could put on the right of an = can go in there, which is most of the language.
f'Hello {student}' with no student anywhere raises NameError: name 'student' is not defined, exactly as it would outside a string. The braces do not create anything — they look up.4Where you will use it most: prompts and answers
An f-string works anywhere a string works, not only inside print() — including as the prompt of an input(), which is where all that 'Enter number ' + str(i + 1) joining came from:
# the reading loop, with the prompt written as a sentence
n = int(input('How many numbers? '))
numbers = []
for i in range(n):
numbers.append(int(input(f'Enter number {i + 1}: ')))
print(f'You entered {len(numbers)} numbers: {numbers}')How many numbers? 3 Enter number 1: 10 Enter number 2: 20 Enter number 3: 30 You entered 3 numbers: [10, 20, 30]
Compare that middle line with the version from the lists chapter — 'Enter number ' + str(i + 1) + ': ' — and the argument for f-strings makes itself. Same output, one str() fewer, and the prompt is readable as a prompt.
5One rule about quotes
An f-string is still a string, so the quote that ends it is still the quote that started it. If the braces need quotes of their own — for a dictionary key, say — use the other kind:
# the inner quotes must differ from the outer ones
marks = {'Asha': 91, 'Ravi': 65}
print(f"Asha scored {marks['Asha']}")
print(f'Ravi scored {marks["Ravi"]}')Asha scored 91 Ravi scored 65
6Recap
The f goes immediately before the opening quote. Without it the braces are ordinary characters and print themselves.
Python's own name for one is a replacement field. Whichever word is used, the whole {…} is replaced by the value it holds.
A name, a sum, a comparison, a function call — anything that has a value. The answer is dropped in where the braces were.
Numbers, True and False and lists all go in as they are. That is the whole reason it beats joining with +.
Usable as an input() prompt, stored in a variable, joined with +. And the inner quotes must differ from the outer ones.
Hello Asha <- f'Hello {name}' — correct
Hello {name} <- 'Hello {name}' — the f was forgotten
Hello name <- f'Hello name' — the braces were forgottenname = 'Asha'. What does print('Hello {name}') show?
What does f'{7} + {3} = {7 + 3}' produce?
Why does f'Enter number {i + 1}: ' need no str()?