Why isn't it possible to use backslashes in f-strings?

13,033

Solution 1

You seem to expect

'{}'.format("new\nline")

and

f'{"new\nline"}'

to be equivalent. That's not what I would expect, and it's not how backslashes in f-strings worked back in the pre-release versions of Python 3.6 where backslashes between the braces were allowed. Back then, you'd get an error because

"new
line"

is not a valid Python expression.

As just demonstrated, backslashes in the braces are confusing and ambiguous, and they were banned to avoid confusion:

The point of this is to disallow convoluted code like:

>>> d = {'a': 4}
>>> f'{d[\'a\']}'
'4'

In addition, I'll disallow escapes to be used for brackets, as in:

>>> f'\x7bd["a"]}'
'4'

(where chr(0x7b) == "{").

Solution 2

It's annoying that you can't do this:

things = ['Thing one','Thing two','Thing three']
print(f"I have a list of things: \n{'\n'.join(things)}")

But you can do this:

things = ['Thing one','Thing two','Thing three']
nl = '\n'
print(f"I have a list of things:\n{nl.join(things)}")

Solution 3

For new lines, you can use os.linesep instead of \n. For example:

>>> import os
>>> 
>>> print(f"Numbers:\n{os.linesep.join(map(str, [10, 20, 30]))}")
Numbers:
10
20
30
Share:
13,033

Related videos on Youtube

jmd_dk
Author by

jmd_dk

Working on simulating cosmic structure formation.

Updated on June 04, 2022

Comments

  • jmd_dk
    jmd_dk almost 2 years

    In Python >=3.6, f-strings can be used as a replacement for the str.format method. As a simple example, these are equivalent:

    '{} {}'.format(2+2, "hey")
    f'{2+2} {"hey"}'
    

    Disregarding format specifiers, I can basically move the positional arguments of str.format inside braces in an f-string. Note specifically that I am allowed to just put str literals in here, although it may seem a bit unwieldy.

    There are however some limitations. Specifically, backslashes in any shape or form are disallowed inside the braces of an f-string:

    '{}'.format("new\nline")  # legal
    f'{"new\nline"}'          # illegal
    f'{"\\"}'                 # illegal
    

    I cannot even use \ to split up a long line if it's inside the braces;

    f'{2+\
    2}'     # illegal
    

    even though this usage of \ is perfectly allowed inside normal str's;

    '{\
    }'.format(2+2)  # legal
    

    It seems to me that a hard stop is coded into the parser if it sees the \ character at all inside the braces of an f-string. Why is this limitation implemented? Though the docs specify this behavior, it does not justify why.

  • Guimoute
    Guimoute about 5 years
    Agreed backslashes in braces are confusing, but backslashes outside are not permitted either and that is too bad. This example is not confusing: f"Make your selection \n A- {textA} \n B- {textB} \n C- {textC}".
  • Rebs
    Rebs about 3 years
    Also the use of textwrap.dedent is totally broken for multi-line f-strings, as the default case is to begin the dedent with a line-continuation `dedent('''\`. This is plain broken imo and the bizarre purist attitudes like this from the py3 devs only serve to hurt the user.
  • Steven Oxley
    Steven Oxley almost 3 years
    @Guimoute Your non-confusing example is perfectly legal (in Python 3.7.8, at least): f"Make your selection \n A- {textA} \n B- {textB} \n C- {textC}". I believe backslashes are only disallowed inside braces.
  • benrg
    benrg over 2 years
    The correct line separator for print is '\n' on all platforms, but on Windows os.linesep is '\r\n' (ref). I think '\n' == chr(10) is guaranteed, so you can write chr(10).join(...), though it feels hacky.