Back to Blog
Python

Python f string repr: Using !r in f-strings

python f string repr: Learn how to use the !r conversion flag in Python f-strings to display repr() output, and how to customize __repr__ for better debugging.

f-stringsreprstring formattingpython debuggingobject representation
Diagram showing how Python f-strings convert objects to string using repr versus str

python f string repr requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

The !r Conversion Flag in f-strings

When you embed an object in an f-string, Python calls str() on it by default. For many objects, that produces a human-readable string, but for debugging, you often need the unambiguous representation that repr() provides. The !r conversion flag forces the f-string to use repr() instead.

value = "hello" print(f"{value}") # hello print(f"{value!r}") # 'hello'

The first line uses str(), the second uses repr(). The difference is clear: repr() adds quotes around strings, making the type explicit.

Why repr() Matters for Debugging

str() is meant for end users; repr() is meant for developers. It should be unambiguous and, where possible, look like valid Python code that could recreate the object. When you log a list or a dictionary, repr() shows the structure with quotes and delimiters, while str() may collapse it or hide details.

items = ["apple", "banana", 42] print(f"{items}") # ['apple', 'banana', 42] print(f"{items!r}") # ['apple', 'banana', 42]

For built-in types, str() and repr() often produce the same output for containers, but for strings and custom objects, they differ significantly.

Using !r with Different Data Types

The !r flag works with any object. Here are a few examples:

from datetime import datetime now = datetime(2024, 3, 15, 10, 30) print(f"{now!r}") # datetime.datetime(2024, 3, 15, 10, 30) class Point: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return f"Point({self.x}, {self.y})" def __str__(self): return f"({self.x}, {self.y})" p = Point(3, 4) print(f"{p}") # (3, 4) print(f"{p!r}") # Point(3, 4)

Notice how repr() for the Point class returns a constructor-like string, which is the recommended pattern.

Customizing repr() in Your Classes

If you want f-strings with !r to be useful for your own classes, define __repr__. A good __repr__ is unambiguous and often includes the class name and the essential attributes.

class InventoryItem: def __init__(self, name, quantity): self.name = name self.quantity = quantity def __repr__(self): return f"InventoryItem(name={self.name!r}, quantity={self.quantity!r})" item = InventoryItem("widget", 3) print(f"{item!r}") # InventoryItem(name='widget', quantity=3)

Using !r inside the __repr__ method itself ensures that string attributes are quoted, making the output more precise.

Common Mistakes and Pitfalls

One common mistake is forgetting the !r flag when you need repr(). This is especially easy when logging or building error messages. Another is using !s explicitly, which is the default and does nothing different. Also, be aware that repr() can raise exceptions if the object's __repr__ is not implemented correctly, but that's rare.

Performance and Maintainability Considerations

Calling repr() is generally fast, but if your __repr__ performs expensive computations (e.g., iterating over a large collection), it can slow down logging in hot paths. For maintainability, keep __repr__ simple and deterministic. Avoid relying on repr() for user-facing output; use str() for that.

Advanced Usage: !a and !s Flags

Python f-strings support three conversion flags: !s (str), !r (repr), and !a (ascii). !a is like repr() but escapes non-ASCII characters. This is useful when you need to ensure the output is ASCII-safe.

text = "café" print(f"{text!a}") # 'caf\\xe9'

You can also combine conversion flags with format specifiers, though the order matters: conversion first, then format spec.

value = 3.14159 print(f"{value!r:10.2f}") # '3.14'

This applies the repr() conversion first, then formats the result as a float with two decimals.

FlagConversionExample (value="hello")
!sstr()hello
!rrepr()'hello'
!aascii()'hello'
python f string repr: Practical Usage and Code Examples | RYUSLOG DEV