2

I'd like to specify a string with both line continuation and catenation characters. this is really useful if I'm echoing a bunch of related values. Here is a simple example with only two parameters:

temp = "here is\n"\
    +"\t{}\n"\
    +"\t{}".format("foo","bar")
print(temp)

here's what I get:

here is
    {}
    foo

And here is what I expect:

here is
    foo
    bar

What gives?

James A. Foster
  • 141
  • 1
  • 1
  • 6

4 Answers4

4

You can try something like this :

temp = ("here is\n"
        "\t{}\n"
        "\t{}".format("foo","bar"))
print(temp)

Or like :

# the \t have been replaced with
# 4 spaces just as an example
temp = '''here is
    {}
    {}'''.format

print(temp('foo', 'bar'))

vs. what you have:

a = "here is\n"
b = "\t{}\n"
c = "\t{}".format("foo","bar")
print( a + b + c)
jmunsch
  • 22,771
  • 11
  • 93
  • 114
3

str.format is called before your strings are concatenated. Think of it like 1 + 2 * 3, where the multiplication is evaluated before the addition.

Just wrap the whole string in parentheses to indicate that you want the strings concatenated before calling str.format:

temp = ("here is\n"
      + "\t{}\n"
      + "\t{}").format("foo","bar")
Blender
  • 289,723
  • 53
  • 439
  • 496
  • 1
    Just remove the `+` concatenation, and leave it to the compiler to concatenate the literals. – Martijn Pieters Jan 29 '18 at 19:10
  • @MartijnPieters: I'll take the performance hit if it means clearer code. Implicit string concatenation has caused me more than enough problems. – Blender Jan 29 '18 at 19:23
2

Python in effect sees this:

Concatenate the result of
    "here is\n"
with the resuslt of
    "\t{}\n"
with the result of
    "\t{}".format("foo","bar")

You have 3 separate string literals, and only the last one has the str.format() method applied.

Note that the Python interpreter is concatenating the strings at runtime.

You should instead use implicit string literal concatenation. Whenever you place two string literals side by side in an expression with no other operators in between, you get a single string:

"This is a single" " long string, even though there are separate literals"

This is stored with the bytecode as a single constant:

>>> compile('"This is a single" " long string, even though there are separate literals"', '', 'single').co_consts
('This is a single long string, even though there are separate literals', None)
>>> compile('"This is two separate" + " strings added together later"', '', 'single').co_consts
('This is two separate', ' strings added together later', None)

From the String literal concatenation documentation:

Multiple adjacent string or bytes literals (delimited by whitespace), possibly using different quoting conventions, are allowed, and their meaning is the same as their concatenation. Thus, "hello" 'world' is equivalent to "helloworld".

When you use implicit string literal concatenation, any .format() call at the end is applied to that whole, single string.

Next, you don't want to use \ backslash line continuation. Use parentheses instead, it is cleaner:

temp = (
    "here is\n"
    "\t{}\n"
    "\t{}".format("foo","bar"))

This is called implicit line joining.

You might also want to learn about multiline string literals, where you use three quotes at the start and end. Newlines are allowed in such strings and remain part of the value:

temp = """\
here is
\t{}
\t{}""".format("foo","bar")

I used a \ backslash after the opening """ to escape the first newline.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1

The format function is only being applied to the last string.

temp = "here is\n"\
    +"\t{}\n"\
    +"\t{}".format("foo","bar")

Is doing this:

temp = "here is\n" + "\t{}\n"\ + "\t{}".format("foo","bar")

The key is that the .format() function is only happening to the last string:

"\t{}".format("foo","bar")

You can obtain the desired result using parentheses:

temp = ("here is\n"\
    +"\t{}\n"\
    +"\t{}").format("foo","bar")
print(temp)

#here is
#   foo
#   bar
pault
  • 41,343
  • 15
  • 107
  • 149