143

I construct a string s in Python 2.6.5 which will have a varying number of %s tokens, which match the number of entries in list x. I need to write out a formatted string. The following doesn't work, but indicates what I'm trying to do. In this example, there are three %s tokens and the list has three entries.

s = '%s BLAH %s FOO %s BAR'
x = ['1', '2', '3']
print s % (x)

I'd like the output string to be:

1 BLAH 2 FOO 3 BAR

SabreWolfy
  • 5,392
  • 11
  • 50
  • 73
  • related: [Formatted string literals in Python 3.6 with tuples](https://stackoverflow.com/q/38763895/10197418) in case you're looking for an f-string based solution. – FObersteiner Oct 12 '22 at 10:05

8 Answers8

189

You should take a look to the format method of python. You could then define your formatting string like this :

>>> s = '{0} BLAH BLAH {1} BLAH {2} BLAH BLIH BLEH'
>>> x = ['1', '2', '3']
>>> print s.format(*x)
'1 BLAH BLAH 2 BLAH 3 BLAH BLIH BLEH'
Cédric Julien
  • 78,516
  • 15
  • 127
  • 132
  • 2
    The OP's problem is not the method but the format of the parameters. `%` operator only unpacks tuples. – patrys Sep 27 '11 at 12:02
  • This would make the construction of `s` more complex, as I would need to include incrementing numbers rather than simply `%s` for each position. `s` is built up in a number of different steps, so it's much easier to just include the `%s` token. – SabreWolfy Sep 27 '11 at 12:02
  • 2
    @SabreWolfy If you construct it precedurally then you might find it easier to name your placeholders and use a dict to format the resulting string: `print u'%(blah)d BLAHS %(foo)d FOOS …' % {'blah': 15, 'foo': 4}`. – patrys Sep 27 '11 at 12:14
  • 2
    @SabreWolfy: In Python 2.7, you can omit the field numbers: `s = '{} BLAH {} BLAH BLAH {} BLAH BLAH BLAH'` – Dennis Williamson Dec 08 '13 at 16:05
  • This answer is potentially confusing, as it makes it look like the numerical values of 0, 1 and 2 are somehow related to the number of times the word "BLAH" appears. – SabreWolfy Apr 21 '20 at 13:30
  • @SabreWolfy edit my answer to avoid repetitions and potential confusion – Cédric Julien Apr 22 '20 at 07:29
  • What is the meaning, or function, of the asterisk (*) ? – kotchwane Nov 15 '20 at 18:48
  • 1
    @kotchwane : the * function is a special python keyword that transform an argument that is a list into a list of arguements :). In our case, *x will pass to the format method the 3 members of x. – Cédric Julien Nov 16 '20 at 07:19
129
print s % tuple(x)

instead of

print s % (x)
infrared
  • 3,566
  • 2
  • 25
  • 37
  • 6
    `(x)` is the same thing as `x`. Putting a single token in brackets has no meaning in Python. You usually put brackets in `foo = (bar, )` to make it easier to read but `foo = bar,` does exactly the same thing. – patrys Sep 27 '11 at 12:10
  • 13
    `print s % (x)` is what OP wrote, I was just quoting him/her. – infrared Sep 27 '11 at 12:12
  • I was just providing a language tip, not criticizing your answer (in fact I +1'd it). You did not write `foo = (bar, )` either :) – patrys Sep 27 '11 at 12:18
  • 3
    I use the `(x)` notation for clarity; it also avoids forgetting the brackets if you later add additional variables. – SabreWolfy Sep 27 '11 at 12:27
  • How about if you want to source your variables from multiple lists? tuple only takes a single list, and the formatter seems to only take a single tuple – curious_prism Jun 17 '14 at 06:47
  • Answered my own question: `print s % (tuple(x) + tuple(y))` – curious_prism Jun 17 '14 at 07:03
  • 1
    This is the best answer! It's much simpler and shorter than the `.format()` one, which is undeservedly the most upvoted one!! – Apostolos Apr 21 '22 at 08:13
45

Following this resource page, if the length of x is varying, we can use:

', '.join(['%.2f']*len(x))

to create a place holder for each element from the list x. Here is the example:

x = [1/3.0, 1/6.0, 0.678]
s = ("elements in the list are ["+', '.join(['%.2f']*len(x))+"]") % tuple(x)
print s
>>> elements in the list are [0.33, 0.17, 0.68]
neobot
  • 1,210
  • 1
  • 14
  • 19
30

Here is a one liner. A little improvised answer using format with print() to iterate a list.

How about this (python 3.x):

sample_list = ['cat', 'dog', 'bunny', 'pig']
print("Your list of animals are: {}, {}, {} and {}".format(*sample_list))

Read the docs here on using format().

geekidharsh
  • 3,549
  • 1
  • 20
  • 24
  • What is the meaning, or function, of the asterisk (*) ? Your link to the documentation does not seem to clarify that. – kotchwane Nov 15 '20 at 18:48
  • 4
    @kotchwane the asterisk "expands" the list as individual ordered arguments. f(\*x) == f(x[0], x[1], ..., x[n]). Similarly, two asterisks (\*\*) expands a dict to keyword arguments. – Wacov Dec 28 '20 at 19:00
21

Since I just learned about this cool thing(indexing into lists from within a format string) I'm adding to this old question.

s = '{x[0]} BLAH {x[1]} FOO {x[2]} BAR'
x = ['1', '2', '3']
print (s.format (x=x))

Output:

1 BLAH 2 FOO 3 BAR

However, I still haven't figured out how to do slicing(inside of the format string '"{x[2:4]}".format...,) and would love to figure it out if anyone has an idea, however I suspect that you simply cannot do that.

Joshua Kan
  • 353
  • 2
  • 7
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
12

This was a fun question! Another way to handle this for variable length lists is to build a function that takes full advantage of the .format method and list unpacking. In the following example I don't use any fancy formatting, but that can easily be changed to suit your needs.

list_1 = [1,2,3,4,5,6]
list_2 = [1,2,3,4,5,6,7,8]

# Create a function that can apply formatting to lists of any length:
def ListToFormattedString(alist):
    # Create a format spec for each item in the input `alist`.
    # E.g., each item will be right-adjusted, field width=3.
    format_list = ['{:>3}' for item in alist] 

    # Now join the format specs into a single string:
    # E.g., '{:>3}, {:>3}, {:>3}' if the input list has 3 items.
    s = ','.join(format_list)

    # Now unpack the input list `alist` into the format string. Done!
    return s.format(*alist)

# Example output:
>>>ListToFormattedString(list_1)
'  1,  2,  3,  4,  5,  6'
>>>ListToFormattedString(list_2)
'  1,  2,  3,  4,  5,  6,  7,  8'
Matt P
  • 2,287
  • 1
  • 11
  • 26
6

For just filling in an arbitrary list of values to a string, you could do the following, which is the same as @neobot's answer but a little more modern and succinct.

>>> l = range(5)
>>> " & ".join(["{}"]*len(l)).format(*l)
'0 & 1 & 2 & 3 & 4'

If what you are concatenating together is already some kind of structured data, I think it would be better to do something more like:

>>> data = {"blah": 1, "foo": 2, "bar": 3}
>>> " ".join([f"{k} {v}" for k, v in data.items()])
'blah 1 foo 2 bar 3'
ryanjdillon
  • 17,658
  • 9
  • 85
  • 110
1
x = ['1', '2', '3']
s = f"{x[0]} BLAH {x[1]} FOO {x[2]} BAR"
print(s)

The output is

1 BLAH 2 FOO 3 BAR
arun n a
  • 684
  • 9
  • 26