-1

I have dabbled in python and run into a situation where I need to break a long f-string containing replacements. I have python 3.6. There seems to be something unique about splitting a f-string with replacements where the general long string splitting techniques fail.

The following are the general questions on SO that provide answers to regular string splitting, and some dubious answers to some of the questions reference f-strings, but none provide an answer to the issue. The prior answers are: PEP8-conform splitting of long f-string, How to write very long string that conforms with PEP8 and prevent E501 and Wrap long lines in Python [duplicate] (references prior link as dupe)

The statement I'm trying to break is:

    def showstate (self):
        print (f"\nstate:\nt  : {round(self.t, 2)}\nx  : {round(self.x, 2)}\ny  : {round(self.y, 2)}\nvx : {round(self.vx, 2)}\nvy : {round(self.vy, 2)}")

An MCVE showing the behavior is:

#! /usr/bin/env python3

if __name__ == "__main__":
    import sys

class MyClass:
    """A simple example class"""
    t = 0.0
    x = 0.
    y = 0.
    vx = 0.
    vy = 0.

    def tstep (self):
        self.t = self.t + 1
        self.y = self.y + self.vy * self.t - .8 * -9.81 * self.t**2
        self.vy = self.vy -9.81 * self.t
    
    def showstate (self):
        print (f"\nstate:\nt  : {round(self.t, 2)}\nx  : {round(self.x, 2)}\ny  : {round(self.y, 2)}\nvx : {round(self.vx, 2)}\nvy : {round(self.vy, 2)}")

x = MyClass()

print (MyClass.__doc__)

x.showstate()
x.tstep()
x.showstate()
x.tstep()
x.showstate()

If you attempt to use adjoining literals, e.g.

    def showstate (self):
        print (f"\nstate:\nt  : {round(self.t, 2)}\nx  : {round(self.x, 2)}\n"
        "y  : {round(self.y, 2)}\nvx : {round(self.vx, 2)}\nvy : {round(self.vy, 2)}")

Then the replacement fields are not replaced, but are printed literally, e.g.

state:
t  : 0.0
x  : 0.0
y  : {round(self.y, 2)}
vx : {round(self.vx, 2)}
vy : {round(self.vy, 2)}

If you add a line continuation, '\', then the whitespace after the continuation is included. For example attempting:

    def showstate (self):
        print (f"\nstate:\nt  : {round(self.t, 2)}\nx  : {round(self.x, 2)}\n\
        y  : {round(self.y, 2)}\nvx : {round(self.vx, 2)}\nvy : {round(self.vy, 2)}")

The output is:

state:
t  : 0.0
x  : 0.0
        y  : 0.0
vx : 0.0
vy : 0.0

Is it possible to break the long f-string in this case and have it print correctly as:

state:
t  : 0.0
x  : 0.0
y  : 0.0
vx : 0.0
vy : 0.0

I can live with the long line, but it seems that it should be capable of being broken to remain within the recommended 79-character style recommendation.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Note this question and answer are NOT duplicates of any of the questions/answers linked in this question. None touch of each portion of a split f-string requiring an individual prefix. – David C. Rankin Jun 29 '21 at 01:44

1 Answers1

1
def showstate (self):
    print (f"\nstate:\nt  : {round(self.t, 2)}\nx  : {round(self.x, 2)}\n"
    "y  : {round(self.y, 2)}\nvx : {round(self.vx, 2)}\nvy : {round(self.vy, 2)}")

You have to provide the f prefix to both literals.

def showstate (self):
    print (f"\nstate:\nt  : {round(self.t, 2)}\nx  : {round(self.x, 2)}\n"
           f"y  : {round(self.y, 2)}\nvx : {round(self.vx, 2)}\nvy : {round(self.vy, 2)}")
         # ^ necessery f prefix

Other ways:

  • You can use line continuation but the second line should be unindented all the way to the left, might trigger some linters:

    def showstate(self):
        print(f"\nstate:\nt  : {round(self.t, 2)}\nx  : {round(self.x, 2)}\n\
    y  : {round(self.y, 2)}\nvx : {round(self.vx, 2)}\nvy : {round(self.vy, 2)}")
    
  • You can use a multiline string, but would also need to be unindented all the way to the left:

    def showstate(self):
         print(f'''\nstate:\nt  : {round(self.t, 2)}\nx  : {round(self.x, 2)}\n
    y  : {round(self.y, 2)}\nvx : {round(self.vx, 2)}\nvy : {round(self.vy, 2)}''') 
    
DeepSpace
  • 78,697
  • 11
  • 109
  • 154
  • 1
    Works like a champ! Thank you. I have been through the language reference, etc.. and hadn't snapped to that simple fact. I'll select the answer when time expires `:)` Yes, I found the line-continuation and full left-justified continued line -- but that just looks horrible. – David C. Rankin Jun 28 '21 at 21:35