5.10 Decorating an Object with Print-Like Methods
Credit: Jürgen Hermann
5.10.1 Problem
You want functionality
similar to that of the print statement on a file
object that is not necessarily standard output, and you want to
access this functionality in an object-oriented manner.
5.10.2 Solution
Statement print is quite handy, but we can emulate
(and optionally tweak) its semantics with nicer, object-oriented
syntax by writing a suitable class:
class PrintDecorator:
""" Add print-like methods to any writable file-like object. """
def _ _init_ _(self, stream, do_softspace=1):
""" Store away the stream for later use. """
self.stream = stream
self.do_softspace = do_softspace
self.softspace = 0
def Print(self, *args, **kw):
""" Print all arguments as strings, separated by spaces.
Take an optional "delim" keyword parameter to change the
delimiting character and an optional "linend" keyword
parameter to insert a line-termination string. Ignores
unknown keyword parameters for simplicity.
"""
delim = kw.get('delim', ' ')
linend = kw.get('linend', '')
if self.do_softspace and self.softspace and args: start = delim
else: start = ''
self.stream.write(start + delim.join(map(str, args)) + linend)
self.softspace = not linend
def PrintLn(self, *args, **kw):
""" Just like self.Print( ), but linend defaults to line-feed.
"""
kw.setdefault('linend','\n')
self.Print(*args, **kw)
if _ _name_ _ == '_ _main_ _':
# Here's how you use this:
import sys
out = PrintDecorator(sys.stdout)
out.PrintLn(1, "+", 1, "is", 1+1)
out.Print("Words", "Smashed", "Together", delim='')
out.PrintLn( )
5.10.3 Discussion
This recipe shows how to decorate objects with new
functions, specifically by decorating an arbitrary writable stream
(file-like object opened for writing) with two methods that work like
the built-in print statement.
The
Print
method takes any number of positional arguments, converts them to
strings (via the map and str
built-ins), joins these strings with the given
delim, then finally writes the resulting string to
the stream. An optional linend, the empty string
by default, allows line termination.
The PrintLn method delegates to
Print, changing the default for the
linend argument to '\n'. Other
ways of sharing common code between Print and
PrintLn run into difficulties�for example,
when delim is nonwhitespace or on multitasking
environments where printing operations need to be atomic (a single
call to the stream's method write
per call to the decorator's Print
or PrintLn methods).
Softspace functionality is also provided to emulate the
print statement's ability to
avoid inserting a useless trailing space if a newline should
immediately follow. This seems simple, and it's
definitely useful, but it can be tricky to implement. Furthermore,
this wrapper supports softspace functionality independently of the
decorated stream's support for setting and getting
the softspace attribute. Softspace behavior can,
however, appear somewhat strange if successive
Print calls use different delim
strings. The softspace functionality can be turned off at
instantiation time.
The code uses Python 2.x syntax (string methods, new-style argument
passing), but it can be easily ported to Python 1.5.2 (if necessary)
by using apply for function calling and the
string module instead of string methods.
5.10.4 See Also
The documentation for the string built-in module
and built-in file objects in the Library
Reference.
|