57

I was writing some lambda functions and couldn't figure this out. Is there a way to have something like lambda x: x if (x<3) in python? As lambda a,b: a if (a > b) else b works ok. So far lambda x: x < 3 and x or None seems to be the closest i have found.

silpol
  • 347
  • 1
  • 10
  • 29
root
  • 76,608
  • 25
  • 108
  • 120

5 Answers5

89

A lambda, like any function, must have a return value.

lambda x: x if (x<3) does not work because it does not specify what to return if not x<3. By default functions return None, so you could do

lambda x: x if (x<3) else None

But perhaps what you are looking for is a list comprehension with an if condition. For example:

In [21]: data = [1, 2, 5, 10, -1]

In [22]: [x for x in data if x < 3]
Out[22]: [1, 2, -1]
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • @ ubuntu -- thank you. Not sure why I assumed it should return None without specifying it. – root Oct 03 '12 at 13:09
  • 7
    That's a reasonable assumption since functions return None by default. The important thing to remember is that what follows `lambda x:` must be an *expression*, not a statement. – unutbu Oct 03 '12 at 13:13
  • 5
    @root I sometimes find it handy to think of a `lambda` as though it's actually written as `def lambda(x, y): return ...` – Jon Clements Oct 03 '12 at 13:33
7

I found that filter provided exactly what I was looking for in python 2:

>>> data = [1, 2, 5, 10, -1]
>>> filter(lambda x: x < 3, data)
[1, 2, -1]

The implementation is different in 2.x and 3.x: while 2.x provides a list, 3.x provides an iterator. Using a list comprehension might make for a cleaner use in 3.x:

>>> data = [1, 2, 5, 10, -1]
>>> [filter(lambda x: x < 3, data)]
[1, 2, -1]
  • The implementation is **not** the same in both 2 and 3. In 2 it returns a list, in 3 it returns an iterator, and to get it into a list, you need to convert it: `list(filter(lambda, data))`. Either way, it's generally considered easier to read a comprehension with an `if` clause like in [unutbu's answer](https://stackoverflow.com/a/12709152/4518341). – wjandrea Nov 21 '20 at 21:00
  • Added your input about python 3, thank you! I suppose the stylistic changes are a bit about personal preference. Lambdas feel a bit natural to me due to using functional programming languages. When I read them, something like `x: x < 3` comes across as less repetitive/more elegant than something like `x for x in data if x [...]`. – im_just_here_to_learn Jan 09 '21 at 00:07
  • Welcome! But your Python3 implementation is incorrect. You get a filter object inside a list. You need to convert it: `list(filter(lambda, data))` or use a splat: `[*filter(lambda x: x < 3, data)]`. It's also not a list comprehension. – wjandrea Jan 09 '21 at 02:14
5

What's wrong with lambda x: x if x < 3 else None?

user4815162342
  • 141,790
  • 18
  • 296
  • 355
3

You can always try to invoke 'filter' for conditional checks. Fundamentally, map() has to work on every occurrence of the iterables, so it cannot pick and choose. But filter may help narrow down the choices. For example, I create a list from 1 to 19 but want to create a tuple of squares of only even numbers.

x = list(range(1,20))

y = tuple(map(lambda n: n**2, filter(lambda n: n%2==0,x)))

print (y)
Gustavo Straube
  • 3,744
  • 6
  • 39
  • 62
Tirtha
  • 598
  • 5
  • 9
  • The answers I was looking for, Thanks. If somehow you can manage to add a 'reduce' statement here and boom we can have one liner functional programming tutorial. – Sourabh Desai Dec 22 '22 at 05:12
1

You can use ellipsis ... to fill else statement

lambda x: x if (x<3) else ... 

Note it does not work with pass.

zigma12
  • 181
  • 1
  • 7