Tuesday, October 26, 2010

Python things you never need: Empty lambda functions

Ever wanted to create an empty Python function in-line?
No?
Me neither.
But my coworker does...
<pre>
x = lambda : None
</pre>

If you ever needed this, please tell me ;)

Apparently some people do need it :)
Btw, most people seem to try
Most people try
lambda: pass

first.
But you have to remember, the thing at the right side of the colon is the return value of the function, not the body! So an expression is needed, not a statement.
[\Edit]

1. Thanks! Yes. I needed it. If you have a better suggestion, I'm all ears, but my scenario involves me trying to discover Autodesk Maya's next script job number and to do so I can't rely on the most recent script job. Instead, I have to create a new script job, get its ID and then just delete it. Thing is, I don't actually want this script job to do anything, but it *requires* a function. So, I need an empty lambda. lambda:pass was improper syntax, but lambda:None works beautifully. Thanks!

2. Yeah, I know that there are some situations where you might need it. It just seems kind of weired ;)

3. Thanks! I needed this as well :)

4. I wanted (using the verb 'need' implies there is no other way around this, which I am unsure of) to do this in order to give an empty function to threading.Timer. Of course lambda:0 or any expression that does not mess with program or system memory (maybe other considerations?) would have done the trick, but sometimes it is nice to use the official null object identifier in order to clarify intent.

5. Technically, it shouldn't ever truly be "necessary" but it is more desirable when the cost of changing source or somebody else's (or your own) code would take way too long. In my case, I wasn't about to modify the threading module. Although there may have been some other workaround.

6. I just used this. I have a dictionary full of lambda functions, and so I did

some_dict.get(the_key, lambda: None)(), which seems to work beautifully.

7. One of my methods has an optional argument that is a callback function. By default it should do nothing, so I needed to test if it was None or not in the function, and then call the callback or not. By defining my argument as "callback = lambda x : None" I eliminate this bothersome test.

8. As far as I know, this is what we call a special case object. So, I disagree with John E on that 'it shouldn't ever truly be "necessary"'. It is as necessary as empty lists, empty sets, empty iterators, empty queues, emptry trees, zeros, ones (neutral element of multiplication) etc.
The emtpy set for instance is the very foundation of every single piece of math we know of today (cf. http://www.science.uva.nl/~seop/entries/set-theory/primer.html). So, declaring this SCO a something unnecessary is quite naive.

Thanks anyway for this pyhton idiom. :) However, the title could be more constructive. ;)

1. I mostly agree with you. The title was never meant to be very serious ;)

The reason that the empty function feels more artificial in Python than an empty list is maybe because I am not a functional programmer (and it is debatable in how far it is possible to write functional code in Python).

So functions don't really feel to me like "just another object" - not claiming that this isn't naive ;)

2. I needed this today when writing testing code; I needed to replace a function in a class I was testing with a do-nothing function.

3. "empty function" is _not_ the same as the rest of your examples. Your "special case object" is in fact neutral element: empty list for concatenation, empty set for union, empty iterator for chaining, zeros for addition, ones for multiplication.

In that sense, "neutral function" is in fact identity: lambda x:x, neutral for composition. lambda:None is something else, kinda like _terminal_ object (something like NaN for numbers) but not quite.

9. There are a myriad of circumstances requiring a null function!

def nul(): pass;

Is perfectly correct python. Following x = nul() (x is None) is True.
Curiously lambda : pass produces a syntax error! Therefore your solution is pythonicly correct.

As a matter of information python is a first rate language for functional programming, particularly higher order functions.

A higher order function is one that accepts a function or functions as parameter and/or returns a function as result.

See here http://docs.python.org/2/library/functools.html for some basic higher order functional techniques.

1. The reason that "pass" throws a syntax error is actually quite simple: lambda requires an expression, not a statement. "pass" is a statement.

2. Which I already said in the post btw ^^

10. I needed this, thanks :)

11. This comment has been removed by the author.

12. Quite useful for me as a default implementation of some expected interface.

13. I've used it as a mock object for error printing during testing:
def run_test(function, params, expected, logger = print):
...

try:
run_test(lambda x : x * 2, 8, 32, lambda x : None)
except RuntimeError:
pass