111

f-Strings are available from Python 3.6 and are very useful for formatting strings:

>>> n='you'
>>> f'hello {n}, how are you?'
'hello you, how are you?'

Reading more about them in Python 3's f-Strings: An Improved String Formatting Syntax (Guide). I found an interesting pattern:

Note that using triple braces will result in there being only single braces in your string:

>>> f"{{{74}}}"
'{74}'

However, you can get more braces to show if you use more than triple braces:

>>> f"{{{{74}}}}"
'{{74}}'

And this is exactly the case:

>>> f'{74}'
'74'

>>> f'{{74}}'
'{74}'

Now if we pass from two { to three, the result is the same:

>>> f'{{{74}}}'
'{74}'           # same as f'{{74}}' !

So we need up to 4! ({{{{) to get two braces as an output:

>>> f'{{{{74}}}}'
'{{74}}'

Why is this? What happens with two braces to have Python require an extra one from that moment on?

Granny Aching
  • 1,295
  • 12
  • 37
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • 70
    It may be illuminating to compare the outputs of `f"{{2+2}}"` and `f"{{{2+2}}}"`, which are `'{2+2}'` and `'{4}'` respectively – Kevin Dec 16 '19 at 15:49
  • 3
    @Kevin great one. It is funny how `f'{2+2}'` returns 4, `f'{{2+2}}'` returns 2+2, `f'{{{2+2}}}'` ➝ {4}, `f'{{{{2+2}}}}'` ➝ {{2+2}} and so on. It makes sense but puzzles a bit on a first sight. – fedorqui Dec 16 '19 at 15:57
  • 2
    Put simply, it's because `f'{74}'` is the same as `f'74'`. – kaya3 Dec 17 '19 at 20:48
  • 1
    This isn't anything new with f-strings, good old `str.format` does this too. – Peilonrayz Dec 18 '19 at 11:27
  • @Peilonrayz How? `"{74}".format(...)` would require a sequence with at least 74 elements. – gerrit Dec 19 '19 at 10:03
  • @gerrit replace `74` with say `n` and it'll be plain as day that it uses the same mechanism. – Peilonrayz Dec 19 '19 at 13:08
  • @Peilonrayz I don't see any way how removing a pair of braces can produce the same result, without f-strings. – gerrit Dec 19 '19 at 13:38
  • @gerrit Have you tried Konrad's examples with `str.format`? It's clearly the same `x = 74;'{{x}}'.format(x=x);'{{{x}}}'.format(x=x)` -> `'{x}'`, `'{74}'`. – Peilonrayz Dec 19 '19 at 14:40
  • @Peilonrayz With `str.format`, in one case the result is `'{x}'`, in the other case it's `'{74}'`. In the question using f-strings, the result is `'{74}'` in both cases. – gerrit Dec 19 '19 at 15:56
  • @gerrit Have you even read Konrad's answer... – Peilonrayz Dec 19 '19 at 15:57
  • @Peilonrayz Yes, and it is entirely clear to me and I have no further questions. It's not the same between f-strings or `str.format`. – gerrit Dec 19 '19 at 16:12
  • @gerrit Well done at proving to yourself something I didn't say. ‎ – Peilonrayz Dec 19 '19 at 18:07

1 Answers1

122

Double braces escape the braces, so that no interpolation happens: {{{, and }}}. And 74 remains an unchanged string, '74'.

With triple braces, the outer double braces are escaped, same as above. The inner braces, on the other hand, lead to regular string interpolation of the value 74.

That is, the string f'{{{74}}}' is equivalent to f'{{ {74} }}', but without spaces (or, equivalently, to '{' + f'{74}' + '}').

You can see the difference when replacing the numeric constant by a variable:

In [1]: x = 74

In [2]: f'{{x}}'
Out[2]: '{x}'

In [3]: f'{{{x}}}'
Out[3]: '{74}'
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214