Skip to content

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 :-)

Posted in Development.

Tagged with , .

17 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Eduardo de Oliveira Padoan says

    If you can use Python2.5 features, a “Conditional Expression” ( is the just the right tool.
    f = lambda x: ‘big’ if x > 100 else ‘small’

  2. Nicolas says

    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 says

    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 says

    Thomas: BAH! ;-)

  5. James Henstridge says

    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 says

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

  7. Nicolas says

    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 says

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

  9. Adriaan says

    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 says

    so after reading this it also means u could just do

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

  11. Adway says

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

  12. MA Nussli says

    The “And”/”Or” solution doesn’t work in any case. At least, I didn’t manage to make it work.

    For example, if your “True statement” is actually a value which is evaluated to a “False” expression(like 0, None, ” or []) then “False statement” will always be returned.
    print (lambda x:x==2 and 0 or 1)(2) —> 1
    print (lambda x:x==2 and 0 or 1)(3) —> 1

    Even worst, if one of the “True/False statements” cannot be evaluated to a boolean expression(like a numpy.array) then it won’t work at all…
    print (lambda x:x==2 and numpy.array([3,4]) or 1)(2)

    Any idea to circumvent such problems??

    • KingRadical says

      >>> print (lambda x: 0 if x == 2 else 1)(2)
      >>> print (lambda x: 0 if x == 2 else 1)(3)

    • KingRadical says

      >>> print (lambda x: np.array([3, 4]) if x == 2 else 1)(2)
      [3 4]

  13. Guest says

    (lambda x: x!=2 and 1 or 0)

  14. James says

    Such an important article. God, this was killing me.

  15. kracekumar says

    I liked this article especially Eduardo de Oliveira Padoan comment

Some HTML is OK

or, reply to this post via trackback.