Seamless sequence output in Python 3.0
We all know how to join things up for output in Python 2.6.
>>> words = ['a', 'list', 'of', 'words'] >>> numbers = 1, 2, 3, 4, 5 >>> print ' '.join(words) a list of words >>> print ' + '.join(str(n) for n in numbers) 1 + 2 + 3 + 4 + 5
String.join does the joining (without any unwanted extra spaces). I often create a bound method, which I think looks a little better:
>>> spaced = ' '.join >>> concat = ''.join >>> spaced(words) 'a list of words' >>> concat(words) 'alistofwords'
String.join()
hasn’t changed in Python 3.0, but print has.
print ' '.join(words) print ' + '.join(str(n) for n in numbers)
Applying the 2to3 converter to the snippet above gives
print(' '.join(words)) print(' + '.join(str(n) for n in numbers))
Alternatively, we can dispense with the explicit string.join
. With some argument unpacking, Python 3.0’s new print function can do it all for us. It also stringifies the printed arguments, so we don’t need the str(n)
’s either.
print(*words) print(*numbers, sep=' + ')
Sys.stdout
is the defaulted destination for the print calls above. Supply a file (or anything with a write(string)
method) to print elsewhere.
If you’re using Python 2.6 but would like to use Python 3.0 style printing, use a future statement.
>>> from __future__ import print_function >>> print(*[1, 2, 3, 4, 5], sep=' + ') 1 + 2 + 3 + 4 + 5 >>> print(1, 2, 3, 4, 5, sep=' + ') 1 + 2 + 3 + 4 + 5
☡ In a comment Fredrik Lundh points out that print
isn’t exactly optimized for handling large numbers of arguments, so the sequence unpacking technique is likely to be slower than using string.join()
. Running a simple timing test confirmed this:
$ python -m timeit -s 'n = list(range(1000))' 'print(*n)' .... 10 loops, best of 3: 27.9 msec per loop $ python -m timeit -s 'n = list(range(1000))' 'print(" ".join(str(i) for i in n))' .... 1000 loops, best of 3: 1.22 msec per loop
That is, the string.join
technique runs about 20 times more quickly when space printing the number range 0 to 999.
Feedback
Did you try benchmarking this? “print” isn’t exactly optimized for handling a large number of arguments. “join” is heavily optimized, though…
(I see about a 15x slowdown in a simple test I made. YMMV.)
Fredrik, good point! No I didn’t try benchmarking, and after posting this entry it did occur to me that print(*things) would probably be slower than print(’ ‘.join(str(thing) for thing in things)).
In my defence: print is something I lean on most heavily during interpreted sessions, when speed isn’t as much of a concern as the keystroke saving, and typically I’m not printing very long sequences anyway.
I’ll run some benchmarks later and put a cautionary note in the article.