Python D-Strings: The End of Multiline String Mess

Python D-Strings: The End of Multiline String Mess

3 min de leitura

If you have ever needed to write a multiline string inside a function or class in Python, you know things get awkward fast.

PEP 822 proposes d-strings (short for dedent) for Python 3.15 — a new syntax that automatically strips indentation from multiline strings. That is the whole idea.

The problem they solve

Say you need to build a text block inside a function:

1
2
3
4
5
6
7
def generate_email(name: str) -> str:
    return textwrap.dedent(f"""\
        Hello, {name}!

        Your registration has been confirmed.
        Thanks for signing up.
    """)

The options we have today are all awkward:

  1. No indentation — breaks the visual flow of the code
  2. String concatenation — verbose and error-prone
  3. textwrap.dedent() — works, but has runtime overhead, is incompatible with t-strings, and requires the ugly """\ opening

D-strings fix all of this with native syntax.

How it works

Just add the d prefix before the triple quotes:

1
2
3
4
5
6
7
def generate_email(name: str) -> str:
    return df"""
        Hello, {name}!

        Your registration has been confirmed.
        Thanks for signing up.
        """

The result is the same text without the extra indentation, no runtime function call needed.

Key rules

  • Only works with triple quotes (""" or ''')
  • Content must begin on the line after the opening quotes
  • The indentation of the closing quotes determines how much is stripped
  • Can be combined with other prefixes: f, r, b, t (in any order)

The closing quote indentation matters

How much indentation gets removed depends on where you place the closing quotes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
s = d"""
    Hello
    World
    """
# Result: 'Hello\nWorld\n'  (4 spaces removed)

s = d"""
    Hello
    World
  """
# Result: '  Hello\n  World\n'  (only 2 spaces removed)

This gives you fine-grained control over the final output without any helper function.

Combining with other prefixes

D-strings work with all the other prefixes you already know:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# df-string: dedent + interpolation
message = df"""
    User: {user}
    Plan: {plan}
    """

# dr-string: dedent + raw (backslashes preserved)
regex_pattern = dr"""
    \d{3}
    \.\d{3}
    \.\d{3}-\d{2}
    """

# dt-string: dedent + template string (Python 3.14+)
template = dt"""
    Hello, {name}!
    Welcome to {system}.
    """

Why not just keep using textwrap.dedent()?

The function exists and works, but it has real limitations:

textwrap.dedent() d-strings
Runtime overhead Yes No
Compatible with t-strings No Yes
Considers closing quote No Yes
Clean syntax Decent Yes

The biggest practical win is compatibility with t-strings (PEP 750, Python 3.14), which are evaluated at compile time and cannot be post-processed with dedent.

Current status

PEP 822 is still a Draft proposal, targeting Python 3.15. A reference implementation already exists (methane/cpython#108), but it still needs to go through the official acceptance process.

Nothing to use in production yet, but it is a genuinely pragmatic addition to what Python already offers. No magic, no overhead — just cleaner syntax for a problem every Python developer has run into.