Python if/else in lambda

Scott, in your “Functional Python” introduction you write:

The one limitation that most disappoints me is that Python lacks is a functional way of writing if/else. Sometimes you just want to do something like this:

lambda x : if_else(x>100, “big number”, “little number”)

(This would return the string “big number” if x was greater than 100, and “little number” otherwise.) Sometimes I get around this by defining my own if_else that I can use in lambda-functions:

def if_else(condition, a, b) :
   if condition : return a
   else         : return b

Actually, you don’t need this helper if_else function at all:

In [1]: f = lambda x: x > 100 and 'big' or 'small'
In [2]: for i in (1, 10, 99, 100, 101, 110):
...:     print i, 'is', f(i)
...:
1 is small
10 is small
99 is small
100 is small
101 is big
110 is big

James, obviously you’re right… Stupid me didn’t think about that. Your version won’t work when a discriminator isn’t known at import time. But even then a function taking *args and **kwargs with a class-like name, returning a correct class instance, would cut the job.

Regarding the module/plugin stuff, I’d rather use setuptools/pkg_resources :-)

11 Responses to “Python if/else in lambda”

  1. Eduardo de Oliveira Padoan said on

    If you can use Python2.5 features, a “Conditional Expression” (http://docs.python.org/whatsnew/pep-308.html) is the just the right tool.
    f = lambda x: ‘big’ if x > 100 else ’small’

  2. Nicolas said on

    Eduardo: didn’t know about that one. I’m still on 2.4 though, both on my personal machine as in our development environment.

  3. Thomas Thurman said on

    Or you can write it as

    f = lambda x: [’small’, ‘big’][x>100]

    Either is pretty ugly, though, and doesn’t read like a real “if-then”. Something I really miss from Perl is being able to declare arbitrary anonymous functions wherever I feel like it.

  4. Nicolas said on

    Thomas: BAH! ;-)

  5. James Henstridge said on

    Nicolas: The simplified version of your metaclass example was functionally equivalent. If you did not know the discriminator at import time, your original version wouldn’t have worked either.

  6. Nicolas said on

    James: I thought the metaclass’ __new__ method is called on every instanciation?

  7. Nicolas said on

    00:55 <ikke> jamesh: isnt __new__ executed on every instanciation?
    00:55 @<jamesh> ikke: yes, but you had a __new__ on the metaclass
    00:55 @<jamesh> ikke: which is executed when you created a new class

    Obviously :-/ Thanks James!

  8. Marius Gedminas said on

    Be very very careful about this X and Y or Z trick. It fails miserably when bool(Y) is False.

  9. Adriaan said on

    Looks like there’s no real solid solution short of a helper function - like Marius said, ( and or ) fails if evaluates to False (the inverse, or and , is even worse), and Thomas’ [, ][not ]) will always evaluate both and , which can be problematic…

    I’m starting to long for the ?: of c :-P

  10. Jo said on

    so after reading this it also means u could just do

    condition and “True statement” or “Falsestatement”
    which seams the easyest solution

  11. Adway said on

    I personally liked the ‘and’ ‘or’ idea. What’s wrong about it?

Leave a comment