Advertisement
Python keeps things simple, which is why so many developers stick with it instead of dealing with heavier languages. But for a long time, formatting strings was one of the clunkier parts of Python. Before version 3.6, you had to use .format() or the old % style—both worked, but they felt awkward and took extra effort to read and write. That changed when f-strings showed up. Suddenly, formatting became quicker and easier to read.
Add an f before the string, toss your variables or expressions into curly braces, and you're done. It reads like plain English. But f-strings go beyond just plugging in values—they let you format numbers, align text, run expressions, and clean up your output without breaking a sweat. If you write Python regularly, getting comfortable with f-strings is one of the simplest ways to make your code cleaner and easier to manage.
This is the most common use. If you’ve got a variable and want to plug it into a string, f-strings make it easy. You just write an f in front of the string and put the variable inside curly braces.
name = "Arjun"
print(f"Hello, {name}")
This replaces {name} with the value of the variable. It feels like regular text, which makes reading and writing code smoother. You can use any number of variables in one string.
age = 28
print(f"{name} is {age} years old.")
No need to worry about order or type—Python handles it under the hood.
You’re not limited to variables. You can put actual expressions inside the curly braces.
a = 5
b = 3
print(f"The sum is {a + b}")
You can even call functions or use method chains.
text = "hello"
print(f"{text.upper()} there")
This cuts down on extra lines just to compute something before printing. It keeps related logic inside the string, where it belongs.
When you want your numbers to look a certain way—maybe with two decimal places or as percentages—f-strings help.
value = 123.45678
print(f"{value:.2f}") # 123.46
The .2f tells Python to format the float to two decimal places. This works well when you’re printing currency or measurements.
For percentages:
score = 0.845
print(f"{score:.1%}") # 84.5%
You can even add commas for large numbers:
amount = 1000000
print(f"{amount:,}") # 1,000,000
Sometimes, you need things to line up. With f-strings, you can align text left, right, or center using <, >, or ^ inside the format specifier.
name = "Priya"
print(f"{name:<10} | left aligned")
print(f"{name:>10} | right aligned")
print(f"{name:^10} | centered")
This is handy in tables or any structured output.
There are times when you want to build strings inside strings. f-strings support that, too.
user = {"name": "Rahul", "score": 95}
print(f"{user['name']} scored {f'{user['score']:.1f}'} points")
While it works, this can get hard to read fast. If you find yourself doing too much nesting, it’s better to break it into parts for clarity.
This is a newer feature from Python 3.8. You can print both the variable and its value with a single syntax using =, which helps with debugging.
x = 42
print(f"{x=}") # x=42
If you include expressions, it shows both the expression and its result.
a = 10
b = 5
print(f"{a + b=}") # a + b=15
It saves you from writing separate strings just to check variable values during testing.
Python lets you use f-strings across multiple lines, especially when writing longer text blocks or formatted messages.
name = "Ayesha"
job = "engineer"
message = (
f"Name: {name}\n"
f"Occupation: {job}\n"
f"Status: Active"
)
print(message)
Each line remains readable, and you still get all the benefits of formatting. This avoids string concatenation or weird line breaks from older methods.
You can access dictionary values and object attributes directly inside f-strings.
person = {"first": "Neha", "last": "Singh"}
print(f"{person['first']} {person['last']}")
With objects:
class Car:
def __init__(self, brand, year):
self.brand = brand
self.year = year
c = Car("Toyota", 2020)
print(f"{c.brand} - {c.year}")
This avoids unpacking or assigning extra variables just to build a string.
When working with datetime objects, f-strings can format them directly using strftime patterns. You don't need to call .strftime() outside the string—you can do it inside the braces.
from datetime import datetime
now = datetime.now()
print(f"Today is {now:%Y-%m-%d}")
This prints something like:
Today is 2025-05-31
You can also format time:
print(f"The current time is {now:%H:%M:%S}")
It works cleanly and keeps formatting close to where you're using the data. It avoids extra lines and improves readability in logs or user messages that need formatted dates.
Sometimes, you want to control whether the string output should be in a readable form (str) or a more detailed version used for debugging (repr). With f-strings, you can do that using !s for str() and !r for repr() directly inside the curly braces.
value = 'hello\nworld'
print(f"{value!s}") # Prints the string as-is
print(f"{value!r}") # Prints the string with escape characters
This is helpful when you want to inspect values that might contain special characters, whitespace, or escape codes. It's especially useful during debugging, testing, or when you’re logging raw data.
f-strings changed the way Python handles string formatting. They make your code tighter and easier to follow. Once you start using them, going back to .format() or % feels like extra work. They’re flexible enough to handle variables, expressions, formatting rules, alignment, and more—all without slowing you down or making the code harder to read. Whether you're working on a script, building logs, or cleaning up old code, knowing how to use f-strings properly can make a real difference. The more you use them, the more you’ll notice how much cleaner your output becomes.
Advertisement
Discover ten easy ways of using ChatGPT to analyze and summarize complex documents with simple ChatGPT prompts.
How LLMs and BERT handle language tasks like sentiment analysis, content generation, and question answering. Learn where each model fits in modern language model applications
Can a small language model actually be useful? Discover how SmolLM runs fast, works offline, and keeps responses sharp—making it the go-to choice for developers who want simplicity and speed without losing quality
Achieve lightning-fast SetFit Inference on Intel Xeon processors with Hugging Face Optimum Intel. Discover how to reduce latency, optimize performance, and streamline deployment without compromising model accuracy
Google risks losing Samsung to Bing if it fails to enhance AI-powered mobile search and deliver smarter, better, faster results
How does Docmatix reshape document understanding for machines? See why this real-world dataset with diverse layouts, OCR, and multilingual data is now essential for building DocVQA systems
Discover the exact AI tools and strategies to build a faceless YouTube channel that earns $10K/month.
Know how AI transforms Cybersecurity with fast threat detection, reduced errors, and the risks of high costs and overdependence
Speed up your deep learning projects with NVIDIA DGX Cloud. Easily train models with H100 GPUs on NVIDIA DGX Cloud for faster, scalable AI development
How can vision-language models learn to respond more like people want? Discover how TRL uses human preferences, reward models, and PPO to align VLM outputs with what actually feels helpful
Watsonx AI bots help IBM Consulting deliver faster, scalable, and ethical generative AI solutions across global client projects
Curious how LLMs learn to write and understand code? From setting a goal to cleaning datasets and training with intent, here’s how coding models actually come together