Learn · Run · Break · Fix
A learning series from A Wandering Mind
Eighteen interlinked lessons on strings, lists, files, exceptions, and dictionaries—with original explanations, runnable examples, real output, and supporting CPSC 1301K lectures.
>>> guide = { ... "lessons": 18, ... "modules": 5, ... "python": "3.10+" ... } >>> guide["goal"] = "understand it"
Formatting Strings and f-strings in Python
F-strings let Python combine text, variables, expressions, and formatting rules without turning a simple print statement into a pile of conversions and plus signs. By the end of this lesson, you will be able to build readable strings, format numbers, align output, and recognize several errors that commonly appear when f-strings go wrong.
print() function. If you want the full sequence, begin from the Python Guide home.What an f-string actually does
A string is text. A variable is a name that points to a value. Most useful programs eventually need to put those two things together: a player's score inside a message, a price inside a receipt, a file name inside a status update, or a calculated percentage inside a report. Python gives you several ways to build that output, but f-strings are usually the clearest choice when the values already exist in your program.
An f-string is an ordinary quoted string with the letter f immediately before the opening quote. Inside the string, curly braces mark places where Python should evaluate something and insert the result. The expression inside the braces can be as simple as a variable name or can perform work such as arithmetic before the final string is produced.
student = "Maya"
completed = 3
print(f"{student} completed {completed} Python exercises.")
Maya completed 3 Python exercises.
The braces are not printed. Python evaluates student and completed, converts their values to text for display, and places them exactly where the braces appeared. That automatic conversion is one reason f-strings are easier to read than manually joining pieces with +. You can see the same advantage again later when we work with lists and need to report values pulled from a collection.
Expressions can go inside the braces
The content inside { } is an expression, not merely a placeholder. Python evaluates it before constructing the finished string. That means you can perform a calculation once, call a simple function, or choose a value and then display the result. Keep the expression reasonably small, though. If a line becomes difficult to scan, calculate the value first and give it a clear variable name.
item = "notebook"
quantity = 4
unit_price = 2.75
total = quantity * unit_price
print(f"{quantity} {item}s cost ${total:.2f}.")
4 notebooks cost $11.00.
The interesting piece is {total:.2f}. Everything before the colon identifies the value. Everything after the colon is a format specification. Here, .2f tells Python to display the number as fixed-point decimal notation with exactly two digits after the decimal point. The value remains a number in the program; only its presentation changes in the resulting string.
Keep data and presentation separate. A format specifier changes how a value looks inside the string. It does not permanently round or alter the original variable. That distinction becomes important when calculations continue after something has been printed.
Useful number formatting without extra code
Format specifications are compact, but they solve common presentation problems. A comma can add thousands separators. A percentage format can multiply a decimal ratio by 100 and add the percent sign. Decimal precision can be controlled without first converting the number to a different type. These tools are especially useful when code starts producing reports rather than isolated values.
{value:,}Turns 384400 into 384,400 for display.
{value:.2f}Shows a numeric value with two digits after the decimal.
{ratio:.1%}Turns 0.8734 into 87.3% for display.
{text:<8}Reserves width and aligns a value within that space.
distance_km = 384400
progress = 0.8734
print(f"Distance: {distance_km:,} km")
print(f"Progress: {progress:.1%}")
Distance: 384,400 km
Progress: 87.3%
Notice that progress is still 0.8734. The percent formatter changes only the string representation. Later, when this guide reaches writing files, the same technique will let us generate clean human-readable reports without sacrificing the numeric values needed by the program.
Alignment makes plain-text output easier to scan
Sometimes the output itself acts like a small table. F-strings can reserve a minimum width for a value and align it inside that space. A less-than sign aligns left, a greater-than sign aligns right, and a caret centers the value. This is not a replacement for a real table in a graphical interface, but it is excellent for terminal output, quick reports, and debugging.
course_totals = [
("Python", 18),
("Java", 12),
("SQL", 9),
]
for language, lessons in course_totals:
print(f"{language:<8} {lessons:>2} lessons")
Python 18 lessons
Java 12 lessons
SQL 9 lessons
This example previews two ideas we will study in detail later: a list stores several items in order, and a loop visits those items one at a time. You do not need to understand either concept yet. The important point here is that <8 gives the language name eight character positions and aligns it left, while >2 reserves two positions for the lesson count and aligns it right.
Common mistakes and what Python is telling you
F-strings remove a lot of conversion work, but they do not make errors disappear. The most useful habit is to read the final line of a traceback first: it names the exception and usually tells you what kind of mismatch occurred. The examples below were deliberately run as failing Python programs so the tracebacks are real rather than invented summaries.
print(f"{student} finished the lesson.")
Traceback (most recent call last):
File "/tmp/lesson1_name.py", line 1, in <module>
print(f"{student} finished the lesson.")
^^^^^^^
NameError: name 'student' is not defined
The f-string is valid, but Python cannot evaluate student because that name has not been assigned a value. Define the variable before the f-string, or correct the name if it was misspelled.
score = "92.5"
print(f"{score:.1f}")
Traceback (most recent call last):
File "/tmp/lesson1_value.py", line 2, in <module>
print(f"{score:.1f}")
^^^^^^^^^^^
ValueError: Unknown format code 'f' for object of type 'str'
The characters 92.5 look numeric to a person, but the quotes make score a string. The f format code expects a numeric value. Store the score as 92.5 without quotes, or deliberately convert validated text with float(). We will return to safer conversion strategies in the lesson on exception handling.
name = "Maya"
print(f"Student: {name")
File "/tmp/lesson1_syntax.py", line 2
print(f"Student: {name")
^
SyntaxError: f-string: expecting '}'
This is a syntax error, so Python cannot start running the program. When the message says an f-string is “expecting '}',” inspect the braces and quotes on that line before looking elsewhere.
lessons = 18
print("Lessons: " + lessons)
Traceback (most recent call last):
File "/tmp/lesson1_type.py", line 2, in <module>
print("Lessons: " + lessons)
~~~~~~~~~~~~^~~~~~~~~
TypeError: can only concatenate str (not "int") to str
This final error is one of the reasons f-strings are so convenient. With print(f"Lessons: {lessons}"), Python handles the display conversion automatically. The integer remains an integer, and the output remains readable.
A supporting classroom explanation
The written lesson is meant to stand on its own. If hearing the same idea explained in a lecture helps it settle, the assigned CPSC 1301K video below provides a second pass at formatted strings. It is supporting material rather than the source of the examples or explanations on this page.
What it adds: a classroom-style walkthrough of formatted strings to reinforce the syntax after you have worked through the examples above.
Try it yourself
Do these without opening the answers first. The goal is not to memorize punctuation; it is to get comfortable predicting what Python will produce when a value appears inside an f-string.
Exercise 1 · Build a weather sentence
Create variables named city and temperature with the values "Savannah" and 84. Use one f-string to print Savannah is 84°F today.
Show one answer
city = "Savannah"
temperature = 84
print(f"{city} is {temperature}°F today.")
Savannah is 84°F today.
Exercise 2 · Format a purchase total
Set price = 7.5 and quantity = 3. Print Total: $22.50 using an f-string and a two-decimal format specification.
Show one answer
price = 7.5
quantity = 3
print(f"Total: ${price * quantity:.2f}")
Total: $22.50
Exercise 3 · Turn a ratio into a percentage
Set completion = 0.625. Use percentage formatting to print Completion: 62.5%.
Show one answer
completion = 0.625
print(f"Completion: {completion:.1%}")
Completion: 62.5%
Where this goes next
F-strings are about turning values into readable text. The next lesson works in the opposite direction: it shows how to take one string and split it into useful pieces, then join pieces back together. That becomes a bridge from plain text into structured data, which is why string manipulation appears before the larger collection topics in this guide.
