2

I have some formatted columns that I'm printing. I would like to use the following variables to set the lengths in my .format arguments

number_length = 5
name_length = 24
viewers_length = 9

I have

print('{0:<5}{1:<24}{2:<9}'.format(' #','channel','viewers'), end = '')

Ideally I would like something like

print('{0:<number_length}{1:<name_length}{2:<viewers_length}'.format(
     ' #','channel','viewers'), end = '')

But this gives me an invalid string formatter error.

I have tried with % before the variables and parenthesis, but have had no luck.

1
  • Can you share what the desired output would be? Commented Feb 4, 2015 at 20:22

3 Answers 3

8

You need to:

  1. Wrap the names in braces, too; and
  2. Pass the widths as keyword arguments to str.format.

For example:

>>> print("{0:>{number_length}}".format(1, number_length=8))
       1

You can also use dictionary unpacking:

>>> widths = {'number_length': 8}
>>> print("{0:>{number_length}}".format(1, **widths))
       1

str.format won't look in the local scope for appropriate names; they must be passed explicitly.

For your example, this could work like:

>>> widths = {'number_length': 5,
              'name_length': 24,
              'viewers_length': 9}
>>> template= '{0:<{number_length}}{1:<{name_length}}{2:<{viewers_length}}'
>>> print(template.format('#', 'channel', 'visitors', end='', **widths))
#    channel                 visitors

(Note that end, and any other explicit keyword arguments, must come before **widths.)

Sign up to request clarification or add additional context in comments.

Comments

2

I'd do it like this

In [11]: widths = dict(number=5, name=24, viewers=9)

In [12]: data = ('#', 'channel', 'viewers')

In [13]: '{:<{number}}{:<{name}}{:<{viewers}}'.format(*data, **widths)
Out[13]: '#    channel                 viewers  '

Of course, it's also possible to generate the format string, without actually getting it formatted:

In [14]: '{{:<{number}}}{{:<{name}}}{{:<{viewers}}}'.format(**widths)
Out[14]: '{:<5}{:<24}{:<9}'

1 Comment

The extra step with doubled braces is potentially superfluous; you can have nested single braces and pass the widths and values to be formatted at the same time.
1

You can build your format string first

f = '{0:<%d}{1:<%d}{2:<%d}' % (number_length, name_length, viewers_length)
#produces
'{0:<5}{1:<24}{2:<9}'

Then use that in your other format call

print(f.format(' #','channel','viewers'), end = ''))

2 Comments

It seems rather odd to mix two different string formatting styles!
Perfect, thank you. Didn't know you could do this. I also like this because I have to use this formatting more than once, so building it a single time is preferable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.