Revision 17 as of 2005-09-03 07:10:09

Clear message

This page discusses the benefits of replacing the current print statement with an equivalent builtin. The write and writeln functions presented below do everything the print statement does without requiring any hacking of the grammar, and also make a number of things significantly easier.

Guido has made it clear he wants to get rid of the print statement in ["Python 3.0"]. This page considers why we want to go that way, and how we can actually get there. It will probably be turned into a PEP at some point.

Benefits of using a function instead of a statement

Getting there from here

The example implementation below shows that creating a function with the desired behaviour is quite straightforward. However, calling the builtin print is a problem due to the fact that print is a reserved word in Python 2.x. Since the print statement will be around until Py3K allows us to break backwards compatibility, devising a transition plan that lets programmers 'get ready early' for the Py3K transition becomes a significant challenge.

If, on the other hand, the builtin has a different name, it is quite feasible to introduce it during the 2.x series. In [http://www.python.org/peps/pep-3000.htm PEP 3000], it is suggested that the print statement be replaced by two builtins: write and writeln. These names are used in the example below. By using alternative names, and providing the builtins in the 2.x series, it is possible to 'future-proof' code against the removal of the print statement in Py3k.

This technique of having two printing operations is not uncommon - Java has both print and println methods, and C# has Write and WriteLine.

Some other names for the builtins which have been suggested are:

Sample implementation

This is a Python 2.4 compatible sample implementation. This version of writeln doesn't provide a linesep keyword argument in order to keep things simple.

   1 def write(*args, **kwds):
   2     """Functional replacement for the print statement
   3 
   4     This function does NOT automatically append a line separator (use writeln for that)
   5     """
   6     # Nothing to do if no positional arguments
   7     if not args:
   8         return
   9     # Parse the keyword-only optional arguments
  10     kwd_values = {
  11         "sep": " ",
  12         "stream": sys.stdout,
  13     }
  14     for name, default in kwd_values.items():
  15         try:
  16             item = kwds[name]
  17         except KeyError:
  18             continue
  19         del kwds[name]
  20         if item is not None:
  21             kwd_values[name] = item
  22     if kwds:
  23         raise TypeError("%s is an invalid keyword argument for this function" % kwds.keys()[0])
  24     sep, stream = kwd_values["sep"], kwd_values["stream"]
  25     # Perform the print operation without building the whole string
  26     stream.write(str(args[0]))
  27     for arg in args[1:]:
  28         stream.write(sep)
  29         stream.write(str(arg))
  30 
  31 def writeln(*args, **kwds):
  32     """Functional replacement for the print statement
  33 
  34     >>> writeln(1, 2, 3)
  35     1 2 3
  36     >>> writeln(1, 2, 3, sep='')
  37     123
  38     >>> writeln(1, 2, 3, sep=', ')
  39     1, 2, 3
  40     >>> import sys
  41     >>> writeln(1, 2, 3, stream=sys.stderr)
  42     1 2 3
  43     >>> writeln(*range(10))
  44     0 1 2 3 4 5 6 7 8 9
  45     >>> writeln(*(x*x for x in range(10)))
  46     0 1 4 9 16 25 36 49 64 81
  47     """
  48     # Perform the print operation without building the whole string
  49     write(*args, **kwds)
  50     write("\n", **kwds)

Code comparisons

These are some comparisons of current print statements with the equivalent code using the builtins write and writeln.

   1 # Standard printing
   2 print 1, 2, 3
   3 writeln(1, 2, 3)
   4 
   5 # Printing without any spaces
   6 print "%d%d%d" % (1, 2, 3)
   7 writeln(1, 2, 3, sep='')
   8 
   9 # Print as comma separated list
  10 print "%d, %d, %d" % (1, 2, 3)
  11 writeln(1, 2, 3, sep=', ')
  12 
  13 # Print without a trailing newline
  14 print 1, 2, 3,
  15 write(1, 2, 3)
  16 
  17 # Print to a different stream
  18 print >> sys.stderr, 1, 2, 3
  19 writeln(1, 2, 3, stream=sys.stderr)
  20 
  21 # Print a simple sequence
  22 print " ".join(map(str, range(10)))
  23 writeln(*range(10))
  24 
  25 # Print a generator expression
  26 print " ".join(str(x*x) for x in range(10))
  27 writeln(*(x*x for x in range(10)))

Unable to edit the page? See the FrontPage for instructions.