292

I'm trying to write PEP-8 compliant code for a domestic project and I have a line with an f-string that is more than 80 characters long:

def __str__(self):
    return f'{self.data} - {self.time},\nTags: {self.tags},\nText: {self.text}'

I'm trying to split it into different lines in the most Pythonic way but the only answer that actually works is an error for my linter.

Working code:

def __str__(self):
    return f'{self.date} - {self.time},\nTags:' + \
    f' {self.tags},\nText: {self.text}'

Output:

2017-08-30 - 17:58:08.307055,
Tags: test tag,
Text: test text

The linter thinks that I'm not respecting E122 from PEP-8, is there a way to get the string right and the code compliant?

7
  • You dont have to return it all on one line, create a base string in a variable then append each part using +=. Then just return the variable. The reason it doesnt comply with E122 is possibly because you aren't indenting the following line. Commented Aug 30, 2017 at 16:07
  • What's the full description of E122?
    – Josh Lee
    Commented Aug 30, 2017 at 16:08
  • 2
    or just tell your ide to increase the line character limit, or ignore that rule all together Commented Aug 30, 2017 at 16:13
  • 4
    @JoshLee "E122 continuation line missing indentation or outdented main" also why you closed the question? There are no duplicates, its the only one about multiline f-strings
    – Owlzy
    Commented Aug 30, 2017 at 16:18
  • 3
    @Owlzy Isn't the answer the exact same: use parenthesis, not the line-continuation marker?
    – Nick T
    Commented Aug 30, 2017 at 16:26

5 Answers 5

389

From Style Guide for Python Code:

The preferred way of wrapping long lines is by using Python's implied line continuation inside parentheses, brackets and braces.

Given this, the following would solve your problem in a PEP-8 compliant way.

return (
    f'{self.date} - {self.time}\n'
    f'Tags: {self.tags}\n'
    f'Text: {self.text}'
)

Python strings will automatically concatenate when not separated by a comma, so you do not need to explicitly call join().

11
  • 5
    No problems on Windows. The \n is platform agnostic as Python has had universal newlines enabled by default since 3.0.
    – noddy
    Commented Jan 26, 2021 at 16:25
  • 2
    Oh yes, I tried this and it worked. Forgot to update here. Good old Python :').
    – shinvu
    Commented Jan 27, 2021 at 11:50
  • 2
    Keep in mind that this is probably less efficient than doing one big f-string, because of extra intermediate (de-)allocations and copying. But it is a good tradeoff for more readable code! Commented Dec 3, 2021 at 9:27
  • 5
    @MattiasWallin This generates the exact same bytecode as one big f-string would. Commented Aug 8, 2023 at 12:30
  • 4
    @MateenUlhaq Correct! Tested in Compiler explorer. This answer suggests it is concatenated during parsing. Reference manual says it is equivalent to concatenated version. Commented Aug 9, 2023 at 9:56
95

I think it would be

return f'''{self.date} - {self.time},
Tags: {self.tags},
Text: {self.text}'''
10
  • 1
    now that its closed i can delete this answer if people think i should ... but its not covered in the dupe answer :/\ Commented Aug 30, 2017 at 16:11
  • 11
    but this kind of multiline defeats the purpose of f-strings and indentation Also I dont feel like this is the right use of the triple quote strings, feels like an hack
    – Owlzy
    Commented Aug 30, 2017 at 16:23
  • 6
    While this answer does replicate the OP's intent, I feel like @noddy's answer is better. This answer just happens to be correct because the OP also wanted multi-line in the output. If you wanted the output to have a different layout than the source code, triple quotes are not the way to go. Commented Nov 13, 2019 at 9:47
  • 1
    Looks nice, but creates problems with indentation and code layout.
    – DZet
    Commented Mar 31, 2021 at 11:56
  • 2
    mix this with the builtin inspect.cleandoc function and you'll have a good day :) Commented May 14, 2021 at 6:31
88

You can use either triple single quotation marks or triple double quotation marks, but put an f at the beginning of the string:

Triple Single Quotes

return f'''{self.date} - {self.time},
Tags:' {self.tags},
Text: {self.text}'''

Triple Double Quotes

return f"""{self.date} - {self.time},
Tags:' {self.tags},
Text: {self.text}"""

Notice that you don't need to use "\n" because you are using a multiple-line string.

2
  • 5
    Good point about "\n" - and here is another reference that also explains it's not necessary for multiline Strings (in section, "Multiline Strings with Triple Quotes").
    – cellepo
    Commented May 18, 2021 at 17:33
  • To avoid braking, curly brackets {} can be escaped by doing {{}}.
    – kta
    Commented Sep 5, 2023 at 2:57
33

As mentioned by @noddy, the approach also works for variable assignment expression:

var1 = "foo"
var2 = "bar"
concat_var = (f"First var is: {var1}"
              f" and in same line Second var is: {var2}")
print(concat_var)

should give you:

First var is: foo and in same line Second var is: bar
12

You can mix the multiline quoting styles and regular strings and f-strings:

foo = 'bar'
baz = 'bletch'
print(f'foo is {foo}!\n',
      'bar is bar!\n',
      f"baz is {baz}!\n",
      "not f-string version: baz is {baz}!\n",
      '''bletch
      is
      bletch!''')

Prints this (note the indentation):

foo is bar!
 bar is bar!
 baz is bletch!
 not f-string version: baz is {baz}!
 bletch
      is
      bletch!

Not the answer you're looking for? Browse other questions tagged or ask your own question.