Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Style for continued multi-line f-strings [closed]

Do any popular Python style guides express a preference between:

x = (f'One plus one is '
     f'equal to {1+1}')

and:

x = ('One plus one is '
     f'equal to {1+1}')

Does it make sense to omit the f prefix for lines that don't involve interpolation? Should it be included for consistency?

like image 295
alecbz Avatar asked Jan 26 '18 23:01

alecbz


1 Answers

If you look at the generated byte code for each of those two options, you will see that this both results in the same set of operations:

>>> dis.dis("""f'One plus one is ' f'equal to {1+1}'""")
  1           0 LOAD_CONST               0 ('One plus one is equal to ')
              2 LOAD_CONST               1 (2)
              4 FORMAT_VALUE             0
              6 BUILD_STRING             2
              8 RETURN_VALUE
>>> dis.dis("""'One plus one is ' f'equal to {1+1}'""")
  1           0 LOAD_CONST               0 ('One plus one is equal to ')
              2 LOAD_CONST               1 (2)
              4 FORMAT_VALUE             0
              6 BUILD_STRING             2
              8 RETURN_VALUE

So for Python, this both does exactly the same thing: The string is being concatenated at compile-time, and the whole string is being evaluated as a format string.

Note though that as per the PEP, f-strings are actually concatenated at run-time, to make sure that every format expression is evaluated independently:

Adjacent f-strings and regular strings are concatenated. Regular strings are concatenated at compile time, and f-strings are concatenated at run time.

That is why the following example will generate two FORMAT_VALUE opcodes:

>>> dis.dis("""f'{2+2}' f'{3+3}'""")
  1           0 LOAD_CONST               0 (4)
              2 FORMAT_VALUE             0
              4 LOAD_CONST               1 (6)
              6 FORMAT_VALUE             0
              8 BUILD_STRING             2
             10 RETURN_VALUE

This will not have an effect for f-strings that don’t actually contain any format placeholders though. Those will still be concatenated at compile-time:

>>> dis.dis("""f'foo' f'bar'""")
  1           0 LOAD_CONST               0 ('foobar')
              2 RETURN_VALUE

So you can just include the f prefix for constant strings anyway and when they don’t contain a format expression, they won’t end up being handled as format strings.

So in your particular case, since there is no functional difference and both options are compiled to the same thing, that leaves this as a pure style choice which everyone has to answer for themselves.

If you are looking at existing style guides, chances are that they are not covering f-strings yet. But then, you could use the same guideline as for raw strings, although I personally don’t expect style guides to really cover that area much. Just choose what looks best, is readable, and what makes most sense to you. After all, continued strings are not really that common (and you are more likely to have triple-quotes for longer strings).

like image 96
poke Avatar answered Oct 03 '22 04:10

poke