2

Let me preface this with the fact that I love both pylint and f-strings. Unfortunately, company policy mandates a maximum line length and using long f-strings is disagreeing with that policy. For example:

xyzzy = f'Let us pretend this line (from {first_name} {last_name}) is too long')

I know that, with str.format(), there's a fairly easy way to do it:

xyzzy = 'Let us pretend this line (from {} {}) is too long'.format(
    first_name, last_name)

However, I don't really want to give up the main benefit of f-strings, the ability to have the data inline with the surrounding text, so I don't have to go looking for it.

I could do two separate f-string and concatenate them with +, but that seems a bit wasteful.

Is there a way to do a single f-string but broken up in such a way as to stop pylint complaining about the length? I'm thinking something like the following (mythical) method where it does what C does in auto-magically concatenating string literals:

xyzzy = f'Let us pretend this line (from {first_name} '
        f'{last_name}) is too long')

Note there's not much structural difference between that and one with + at the end of the first line, but I suspect the latter would be two distinct operations in the byte-code.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953

4 Answers4

2

I guess in your case it is best to use the usual line continuation method using a backslash \:

xyzzy = f'Let us pretend this line (from {first_name} ' \
        f'{last_name}) is too long')

Note that it generates the same bytecode as a single line:

>>> def foo():
...   return "long line"
... 
>>> def bar():
...   return "long " \
...   "line"
... 
>>> dis.dis(foo)
  2           0 LOAD_CONST               1 ('long line')
              2 RETURN_VALUE
>>> dis.dis(bar)
  2           0 LOAD_CONST               1 ('long line')
              2 RETURN_VALUE

That being said, CPython compiler is pretty smart when it comes to simple optimisations:

>>> def foobar():
...   return "long " + "line"
... 
>>> dis.dis(foobar)
  2           0 LOAD_CONST               1 ('long line')
              2 RETURN_VALUE
Selcuk
  • 57,004
  • 12
  • 102
  • 110
  • I thought maybe that would not work with f-strings but it does. It optimises the intermixed string constants and calculated values in the same manner as if I had the whole thing on one line. – paxdiablo Jul 16 '21 at 10:35
  • It gives following warning message: `‘\’: E502 the backslash is redundant between brackets` – alper Dec 04 '21 at 16:50
  • @alper There are no brackets in the example. Also _what_ gives that warning? Those are pylint warnings, nothing to do with CPython. – Selcuk Dec 05 '21 at 22:50
  • I was getting them in `pylint`. Ah if I create them inside `print()` , brackets of `print` will cause the warning message – alper Dec 06 '21 at 09:04
1

I found the following three ways to solve this issue:

first_name = 'John'
last_name = 'Doe'

foo = f'Let us pretend this line (from {first_name} ' \
    f'{last_name}) is too long ' \
    f'Let us pretend this line (from {first_name} ' \
    f'{last_name}) is too long'

bar = f"""Let us pretend this line (from {first_name}
{last_name}) is too long
Let us pretend this line (from {first_name}
{last_name}) is too long""".replace('\n', ' ')

xyz = (
    f'Let us pretend this line (from {first_name} '
    f'{last_name}) is too long '
    f'Let us pretend this line (from {first_name} '
    f'{last_name}) is too long'
)

I personally think that the last variant looks the cleanest, but if you want to use a single f-string, then see the second option. More ideas can be found at a similar question.

Spuu
  • 11
  • 4
1

You can surround the string by parenthesis and use python's implicit concatenation of string:

xyzzy = (
    f'Let us pretend this line (from {first_name} '
    f'{last_name}) is too long).'
    ' This is a non f-string part of the string'
)

Black can do that semi-automatically you just have to add a 'f' inside your string after the 87th character and apply auto-formatting (or "f" after the first time you apply it).

Pierre.Sassoulas
  • 3,733
  • 3
  • 33
  • 48
0

The best way would be to concatenate with a backslash (\):

xyzzy = f'Let us pretend this line (from {first_name} ' \
    f'{last_name}) is too long')

Or with a not recommended way :)

xyzzy = ''.join((f'Let us pretend this line (from {first_name} ', 
    f'{last_name}) is too long'))
U13-Forward
  • 69,221
  • 14
  • 89
  • 114