Sunday, July 02, 2006

Python: using print with lambda

In the Python programming language, print is a statement, not a function. (This has been recognised as a design flaw, and will be corrected in Python 3.) One of the disadvantages of that is that you can't use print in anonymous functions using lambda.

However, there are work arounds.

Firstly, the simplest: create your own print function:

def prnt(x):
    """Print object x."""
    print x

And now you can write lambda obj: prnt(obj).

Too easy? Here's a marginally more complex solution. If you know that your code has imported the sys module, you can do this:

lambda obj: sys.stdout.write(str(obj)+'\n')

What if you can't assume that some other piece of code has called import sys for you? There are those who claim that the right behaviour is to raise an exception if sys hasn't been imported, which Python will kindly do for you at runtime. Others prefer to import it when needed:

lambda obj: __import__("sys").stdout.write(str(obj)+'\n')

Of course, the real print statement takes optionally many arguments, printing them separated with a single space. Can we do that?

A list comprehension makes it easy:

lambda *args: __import__("sys").stdout.write(
" ".join([str(obj) for obj in args])+'\n')

The __import__ function, like the import statement, is smart about importing modules. If the module has already been imported, it doesn't do anything, so importing an already imported function has negligible penalty.

The real print has subtly different behaviour if you end its argument list with a trailing comma: it doesn't print a trailing newline. Our lambda can't capture that behaviour, but this gives you almost all the functionality of print within an anonymous function.

No comments: