71

If I want to make my formatted string dynamically adjustable, I can change the following code from

print '%20s : %20s' % ("Python", "Very Good")

to

width = 20
print ('%' + str(width) + 's : %' + str(width) + 's') % ("Python", "Very Good")

However, it seems that string concatenation is cumbersome here. Any other way to simplify things?

aschultz
  • 1,658
  • 3
  • 20
  • 30
Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875

5 Answers5

121

You can do this using the str.format() method.

>>> width = 20
>>> print("{:>{width}} : {:>{width}}".format("Python", "Very Good", width=width))
              Python :            Very Good

Starting from Python 3.6 you can use f-string to do this:

In [579]: lang = 'Python'

In [580]: adj = 'Very Good'

In [581]: width = 20

In [582]: f'{lang:>{width}}: {adj:>{width}}'
Out[582]: '              Python:            Very Good'
styvane
  • 59,869
  • 19
  • 150
  • 156
42

You can fetch the padding value from the argument list:

print '%*s : %*s' % (20, "Python", 20, "Very Good")

You can even insert the padding values dynamically:

width = 20
args = ("Python", "Very Good")
padded_args = zip([width] * len(args), args)
# Flatten the padded argument list.
print "%*s : %*s" % tuple([item for list in padded_args for item in list])
Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
33

For those who want to do the same thing with python 3.6+ and f-Strings this is the solution.

width = 20
py, vg = "Python", "Very Good"
print(f"{py:>{width}s} : {vg:>{width}s}")
Praveen Kulkarni
  • 2,816
  • 1
  • 23
  • 39
  • 2
    Thank you. This was exactly what I was looking for. An additional question, what is the purpose of the '>' in front of the variable? I've seen others with '0' in front. Is there a significance? – Heather Claxton Jan 17 '21 at 23:07
  • 2
    Actually, I just found my answer. The '>' and '<' are for right alignment and left alignment of the number respectively. Here's the source: http://cis.bentley.edu/sandbox/wp-content/uploads/Documentation-on-f-strings.pdf – Heather Claxton Jan 18 '21 at 17:12
8
print '%*s : %*s' % (width, 'Python', width, 'Very Good')
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
2

If you don't want to specify the widths at the same time, you can prepare a format string ahead of time, like you were doing - but with another substitution. We use %% to escape actual % signs in a string. We want to end up with %20s in our format string when the width is 20, so we use %%%ds and supply the width variable to substitute in there. The first two % signs become a literal %, and then %d is substituted with the variable.

Thus:

format_template = '%%%ds : %%%ds'
# later:
width = 20
formatter = format_template % (width, width)
# even later:
print formatter % ('Python', 'Very Good')
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • 1
    I like this as a way to dynamically generate format strings in general. However, Mr. Hamidi's approach is better if only the field widths are to be dynamically interpolated. – Jim Dennis Nov 29 '10 at 09:29