21

I'm trying to do this:

max_title_width = max([len(text) for text in columns])

for column in columns:
    print "%10s, blah" % column

But I want to replace the 10 with the value of max_title_width. How do I do this in the most pythonic way possible?

1
  • 4
    In Python 2.4 and later, the []'s are unnecessary in your computation of max_title_width - they just build a list that you immediately discard after computing the max. See python.org/dev/peps/pep-0289. Commented Sep 19, 2009 at 16:08

4 Answers 4

48

This is a carryover from the C formatting markup:

print "%*s, blah" % (max_title_width,column)

If you want left-justified text (for entries shorter than max_title_width), put a '-' before the '*'.

>>> text = "abcdef"
>>> print "<%*s>" % (len(text)+2,text)
<  abcdef>
>>> print "<%-*s>" % (len(text)+2,text)
<abcdef  >
>>>

If the len field is shorter than the text string, the string just overflows:

>>> print "<%*s>" % (len(text)-2,text)
<abcdef>

If you want to clip at a maximum length, use the '.' precision field of the format placeholder:

>>> print "<%.*s>" % (len(text)-2,text)
<abcd>

Put them all together this way:

%
- if left justified
* or integer - min width (if '*', insert variable length in data tuple)
.* or .integer - max width (if '*', insert variable length in data tuple)
Sign up to request clarification or add additional context in comments.

1 Comment

wow, great trick! I didn't know that about the left/right padding.
22

You have the new strings formatting methods from Python 3 and Python 2.6.

Starting in Python 2.6, the built-in str and unicode classes provide the ability to do complex variable substitutions and value formatting via the str.format() method described in PEP 3101. The Formatter class in the string module allows you to create and customize your own string formatting behaviors using the same implementation as the built-in format() method.

(...)

For example, suppose you wanted to have a replacement field whose field width is determined by another variable:

>>> "A man with two {0:{1}}.".format("noses", 10)
"A man with two noses     ."
>>> print("A man with two {0:{1}}.".format("noses", 10))
A man with two noses     .

So for your example it would be

max_title_width = max(len(text) for text in columns)

for column in columns:
    print "A man with two {0:{1}}".format(column, max_title_width)

I personally love the new formatting methods, as they are far more powerful and readable in my humble opinion.

1 Comment

I had no idea you could do this... At first I was going to say this felt unnatural, but after thinking about it, I guess it makes sense!
3

Python 2.6+ alternate version examples:

>>> '{:{n}s}, blah'.format('column', n=10)
'column    , blah'
>>> '{:*>{l}s}'.format(password[-3:], l=len(password)) # password = 'stackoverflow'
'**********low'
>>> '{:,.{n}f} {}'.format(1234.567, 'USD', n=2)
'1,234.57 USD'

Hint: first non-keyword args, then keyword args.

Comments

2

you could create your template outside of the loop:

tmpl = '%%%ds, blah' % max_title_width
for column in columns:
    print tmpl % column

You could also learn about the new formatting in python.

and btw, max doesn't require a list, you can pass it an iterable:

max_title_width = max(len(i) for i in columns)

4 Comments

max(columns, key=len) returns an element from columns. The Original Poster's code gets the length of the longest column…
well caught, what was I thinking.
Wasn't me, but probably because it's more pythonic to specify the width with the * specifier.
huh? more pythonic? he's printing in the loop, how is it more pythonic to use obscure syntax and expand the asterisk at each iteration?

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.