[Python-Dev] Replacement for print in Python 3.0

Nick Coghlan ncoghlan at gmail.com
Sat Sep 3 03:02:43 CEST 2005


Steven Bethard wrote:
> Well, my proposal (which differs from Guidos) is that the print
> function (or whatever it ends up getting called) would have the
> semantics:
> 
>     def print(*args):
>         sys.stdout.write(' '.join(str(arg) for arg in args))
>         sys.stdout.write('\n')

I'd rather see a signature with the expressiveness of the current print 
statement (full implementation below). I've called it 'output' rather than 
'print' so that copy and pasting it into a 2.4 interactive session will work 
(I also think the symmetry with input is cute).

With this function:

print 1, 2, 3 => output(1, 2, 3)

print >> sys.stderr, 1, 2, 3 => output(1, 2, 3, stream=sys.stderr)

print "%d%d%d" % (1, 2, 3) => output(1, 2, 3, sep='')

print 1, 2, 3, => output(1, 2, 3, end='')

Printing a tab-separated or comma separated list becomes trivial:

print "%d, %d, %d" % (1, 2, 3) => output(1, 2, 3, sep=', ')
print "%d\t%d\t%d" % (1, 2, 3) => output(1, 2, 3, sep='\t')

Printing the items in a sequence also becomes straightforward:

print " ".join(map(str, range(10))) => output(*range(10))

Playing well with generator expressions comes for free, too:

print " ".join(str(x*x) for x in range(10))
     => output(*(x*x for x in range(10)))

The capabilities of the current print statement reveal a lot of collective 
wisdom regarding what is useful - the only real issues are that the syntax is 
somewhat ugly and unique to the print statement, rather than using standard 
function call syntax, and that as a result of the first issue, it is difficult 
to control the behaviour of the separator.

Turning it into a proper function with three keyword arguments (sep, end, 
stream) would allow both of these issues to be addressed, and also provide a 
whole lot of fringe benefits relating to printing of sequences as described above.

Cheers,
Nick.

The sample implementation:

def output(*args, **kwds):
     """Functional replacement for the print statement

     >>> output(1, 2, 3)
     1 2 3
     >>> output(1, 2, 3, sep='')
     123
     >>> output(1, 2, 3, sep=', ')
     1, 2, 3
     >>> output(1, 2, 3, end='Alternate line ending')
     1 2 3Alternate line ending
     >>> import sys
     >>> output(1, 2, 3, stream=sys.stderr)
     1 2 3
     >>> output(*range(10))
     0 1 2 3 4 5 6 7 8 9
     >>> output(*(x*x for x in range(10)))
     0 1 4 9 16 25 36 49 64 81
     """
     # Parse the keyword-only optional arguments
     defaults = {
         "sep": " ",
         "end": "\n",
         "stream": sys.stdout,
     }
     for name, default in defaults.items():
         item = None
         try:
             item = kwds[name]
         except KeyError:
             pass
         if item is None:
             kwds[name] = default
     sep, end, stream = kwds["sep"], kwds["end"], kwds["stream"]
     # Perform the print operation without building the whole string
     for arg in args[:1]:
         stream.write(str(arg))
     for arg in args[1:]:
         stream.write(sep)
         stream.write(str(arg))
     stream.write(end)

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://boredomandlaziness.blogspot.com


More information about the Python-Dev mailing list