paxdiablo
paxdiablo

Reputation: 882326

How do I best handle pylint long-line checks with f-strings?

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.

Upvotes: 4

Views: 1942

Answers (4)

Pierre.Sassoulas
Pierre.Sassoulas

Reputation: 4282

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).

Upvotes: 1

Spuu
Spuu

Reputation: 11

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.

Upvotes: 1

U13-Forward
U13-Forward

Reputation: 71610

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'))

Upvotes: 0

Selcuk
Selcuk

Reputation: 59425

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

Upvotes: 3

Related Questions