Python String Formatting and F-Strings

Ka Kavitha V Updated 03 Oct 2026
7 min read

String Formatting and F-Strings

Programs constantly combine text with values: "Your order total is ₹1,250.00", "Welcome back, Asha!", "Upload 87% complete". String formatting is the process of inserting values into text and controlling how they appear — the number of decimal places, alignment, thousands separators, and more.

Python offers two main tools for this:

  1. F-strings (formatted string literals) — introduced in Python 3.6 and now the recommended approach
  2. The format() method — the older approach, still widely seen in existing code

Before Python 3.6, developers mainly used format() or string concatenation with +, which is more verbose, harder to read, and requires manual conversion with str().

What Are F-Strings?

An f-string lets you embed values and expressions directly inside a string. To create one, put the letter f (or F) before the opening quote.

Example: A Basic F-String

message = f"Welcome to Python programming"
print(message)

Expected output:

Welcome to Python programming

This f-string contains no placeholders, so it behaves like a normal string. The power of f-strings comes from placeholders.

Using Placeholders

Values are inserted into an f-string with curly braces {}. Each pair of braces is a placeholder, and it can contain:

  • Variables
  • Calculations and other expressions
  • Function and method calls
  • Formatting modifiers

Example: Inserting a Variable

score = 88
result = f"Your final score is {score}"
print(result)

Expected output:

Your final score is 88

Python evaluates score, converts its value to text automatically, and inserts it where the placeholder is. No str() conversion is needed.

Comparison With Concatenation

name = "Asha"
age = 25

# Concatenation: requires str() and careful spacing
print("Name: " + name + ", Age: " + str(age))

# F-string: clear and concise
print(f"Name: {name}, Age: {age}")

Expected output:

Name: Asha, Age: 25
Name: Asha, Age: 25

Formatting Values With Modifiers

A format specifier (also called a modifier) controls how a value is displayed. It is written after a colon inside the placeholder:

f"{value:specifier}"

Example: Limiting Decimal Places

average = 7.45678
output = f"Average rating: {average:.2f}"
print(output)

Expected output:

Average rating: 7.46

.2f means "format as a fixed-point number with 2 decimal places". The value is rounded for display only — the variable average is unchanged.

Example: Formatting a Literal Value Directly

output = f"Success rate: {92.347:.1f}%"
print(output)

Expected output:

Success rate: 92.3%

The % after the closing brace is ordinary text.

Performing Operations Inside F-Strings

Any valid Python expression can be placed inside the braces.

Example: Arithmetic

total = f"Total cost: {15 * 120} rupees"
print(total)

Expected output:

Total cost: 1800 rupees

Example: Calculation Using Variables

price = 500
discount = 0.10

final_price = f"Payable amount: {price - (price * discount)}"
print(final_price)

Expected output:

Payable amount: 450.0

The result is a float (450.0) because price * discount produces a float. Adding a modifier, such as {price - (price * discount):.2f}, would display 450.00.

Tip: For complex calculations, compute the value in a separate variable first and then insert it. This keeps f-strings short and readable.

Conditional Logic Inside F-Strings

A conditional expression (value_if_true if condition else value_if_false) can choose what to display.

marks = 72
status = f"Result: {'Pass' if marks >= 40 else 'Fail'}"
print(status)

Expected output:

Result: Pass

Notice that the f-string uses double quotes, while the strings inside the placeholder use single quotes. In Python versions before 3.12, reusing the same quote type inside a placeholder causes a syntax error, so alternating quote types is the safest habit.

Calling Functions Inside F-Strings

Both built-in and user-defined functions — and methods — can be called inside placeholders.

Example: Calling a String Method

city = "chennai"
text = f"I live in {city.title()}"
print(text)

Expected output:

I live in Chennai

title() is a string method that capitalizes the first letter of each word.

Example: Calling a User-Defined Function

def km_to_miles(km):
    return km * 0.621371

distance = f"Distance: {km_to_miles(10):.2f} miles"
print(distance)

Expected output:

Distance: 6.21 miles

The function is called first, and its result (6.21371) is then formatted to two decimal places.

Advanced Formatting Options

Thousands Separator

population = 14500000
info = f"Population: {population:,}"
print(info)

Expected output:

Population: 14,500,000

The comma specifier inserts a comma every three digits. An underscore works the same way: {population:_} produces 14_500_000.

Percentage Format

progress = 0.875
status = f"Completed: {progress:.0%}"
print(status)

Expected output:

Completed: 88%

The % specifier multiplies the value by 100 and adds a percent sign. .0% shows no decimal places, so 87.5% is rounded to 88%. With .1%, the result would be 87.5%.

Alignment and Width

A number before the type sets the minimum width, and <, >, or ^ sets the alignment.

print(f"[{'Hi':<6}]")
print(f"[{'Hi':>6}]")
print(f"[{'Hi':^6}]")

Expected output:

[Hi    ]
[    Hi]
[  Hi  ]

The square brackets show the edges of each 6-character field.

Practical Example: A Formatted Table

items = [("Notebook", 3, 45.0), ("Pen", 10, 12.5), ("Bag", 1, 899.0)]

print(f"{'Item':<10}{'Qty':>5}{'Price':>10}")
for name, qty, price in items:
    print(f"{name:<10}{qty:>5}{price:>10.2f}")

Expected output:

Item        Qty     Price
Notebook      3     45.00
Pen          10     12.50
Bag           1    899.00

Each column has a fixed width, so the values line up neatly regardless of their length.

Number Bases and Signs

print(f"{5:+}")
print(f"{10:b}")
print(f"{255:x}")
print(f"{255:X}")
print(f"{8:o}")
print(f"{12345.678:e}")

Expected output:

+5
1010
ff
FF
10
1.234568e+04

Debugging With =

Since Python 3.8, adding = after an expression prints both the expression and its value — handy for debugging:

x = 5
print(f"{x=}")
print(f"{x * 2=}")

Expected output:

x=5
x * 2=10

Displaying Literal Braces

To show a literal { or } in an f-string, double it:

print(f"{{value}} is replaced by {42}")

Expected output:

{value} is replaced by 42

Common Format Specifiers

SpecifierDescriptionExampleResult
<Left-align within the widthf"{'Hi':<6}"'Hi '
>Right-align within the widthf"{'Hi':>6}"' Hi'
^Center within the widthf"{'Hi':^6}"' Hi '
+Always show the signf"{5:+}"+5
,Comma thousands separatorf"{1000000:,}"1,000,000
_Underscore thousands separatorf"{1000000:_}"1_000_000
bBinaryf"{10:b}"1010
dDecimal integerf"{42:d}"42
fFixed-point numberf"{3.14159:.2f}"3.14
eScientific notationf"{12345.678:e}"1.234568e+04
oOctalf"{8:o}"10
x / XHexadecimal (lower/upper case)f"{255:x}"ff
%Percentagef"{0.875:.1%}"87.5%

String Formatting With format()

Before f-strings, the format() method was the standard way to format strings. It is still supported and useful when a template string is defined separately from the values — for example, a message template loaded from a configuration file. However, f-strings are usually more readable and slightly faster.

format() uses the same {} placeholders and the same format specifiers.

Example: Basic format()

price = 75
text = "The ticket price is {} rupees"
print(text.format(price))

Expected output:

The ticket price is 75 rupees

Example: Formatting Decimals

text = "Temperature: {:.1f}°C"
print(text.format(36.678))

Expected output:

Temperature: 36.7°C

Formatting Multiple Values

Empty placeholders are filled in order with the arguments passed to format().

items = 4
product_id = 210
cost = 349.5

order = "Order: {} items | ID: {} | Cost: {:.2f}"
print(order.format(items, product_id, cost))

Expected output:

Order: 4 items | ID: 210 | Cost: 349.50

Using Index Numbers

Numbers inside the placeholders refer to the position of the arguments, starting at 0. This lets you place values in any order.

order = "Item {1} costs {0:.2f} rupees"
print(order.format(499.99, "Headphones"))

Expected output:

Item Headphones costs 499.99 rupees

{1} takes the second argument ("Headphones"), and {0:.2f} takes the first (499.99) and formats it.

Reusing the Same Value

Index numbers also let you use a value more than once without passing it again.

age = 21
name = "Rahul"

info = "{1} is {0} years old. {1} is learning Python."
print(info.format(age, name))

Expected output:

Rahul is 21 years old. Rahul is learning Python.

Named Placeholders

Named placeholders make templates with many values easier to read.

details = "Car: {brand}, Model: {version}"
print(details.format(brand="Toyota", version="Corolla"))

Expected output:

Car: Toyota, Model: Corolla

F-Strings vs format()

FeatureF-Stringformat()
Available sincePython 3.6Python 2.6 / 3.0
Values appearDirectly inside the stringAs arguments at the end
ReadabilityHighLower with many values
Reusable templatesNo — evaluated immediatelyYes — the template can be stored and reused
Recommended forMost everyday formattingTemplates defined separately from their data

Common Mistakes

MistakeProblem
Forgetting the f prefixThe braces are printed literally: "Score: {score}"
Same quotes inside and outside (Python < 3.12)SyntaxError; alternate " and '
Using .2f on a stringValueError — format specifiers must match the value's type
Mismatched counts in format()IndexError when there are more placeholders than arguments
Expecting formatting to change the variableFormatting only affects the displayed text
  • Python Strings — string basics and concatenation
  • Python Output — displaying text with print()
  • Python Datetime — formatting dates with format codes, which also work in f-strings

0 Comments

Reviewed before they appear

No comments yet.

Python
Ask about this post
AI Ask about this post

Ask questions about Python String Formatting and F-Strings and get answers drawn from it.

Signed-in readers only.