Why isn't it possible to use backslashes inside the braces of f-strings? How can I work around the problem?

Question:

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("newnline")  # legal
f'{"newnline"}'          # 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.

Asked By: jmd_dk

||

Answers:

You seem to expect

'{}'.format("newnline")

and

f'{"newnline"}'

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) == “{“).

Answered By: user2357112

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)}")
Answered By: vy32

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
Answered By: Giorgos Myrianthous

I am not sure if this helps, but instead of the illegal

f'{"newnline"}'

one could use

f'{"new"+chr(10)+"line"}'
Answered By: karpan