tags:

views:

230

answers:

6

I have the following lambda function:

f = lambda x: x == None and '' or x

It should return an empty string if it receives None as the argument, or the argument if it's not None.

For example:

>>> f(4)
4
>>> f(None)
>>>

If I call f(None) instead of getting an empty string I get None. I printed the type of what the function returned and I got NoneType. I was expecting string.

type('') returns string, so I'd like to know why the lambda doesn't return an empty string when I pass None as an argument.

I'm fairly new to lambdas so I might have misunderstood some things about how they work.

+1  A: 

It's not lambdas that are the problem here. It's the pythonic if/else expressiong you are using there.

(condition) and (expression1) or (expression2) most of the times means the (condition) ? (expression1) : (expression2) you'd expect, except when expression1 evaluates to False.

This is because the whole thing is evaluated in order. If condition fails, expression1 is evaluated. If it is True, it is returned, due to short circuit evaluation, hence the expected behaviour. If not, expression2 is returned. '' evaluates to False.

MTsoul
Yeah the and/or pattern is not very Pythonic.. don't use it! Keep It Simple, Stupid!
BlueRaja - Danny Pflughoeft
+7  A: 

The problem in your case that '' is considered as boolean False. bool('') == False. You can use

f =lambda x:x if x is not None else ''
Yaroslav
+1  A: 

Try short-circuit evaluation:

 >>> g = lambda x: x or ''
 >>> g(3)
 3
 >>> g(None)
 ''
 >>> # beware that ...
 >>> g(0)
 ''
The MYYN
I don't think `g(0)` returns what OP wants.
Douglas Leeder
+8  A: 

use the if else construct

f = lambda x:'' if x is None else x
z33m
+2  A: 

Python gives and a higher precedence than or, so the parentheses fall here:

lambda x: (x == None and '') or x

When passed None, this becomes (True and '') or None. Python’s boolean operators work by returning one argument or another (whence this little trick), so this reduces to '' or None, and finally None.

This little trick stems from back before Python 2.5, which didn't have the conditional operator. The caveat, which you just ran into, is that it doesn’t behave as expected when True branch has a False value. Unless you’re concerned with Python ≤ 2.4, just use the conditional operator.

jleedev
+1  A: 

The problem is that Python treats the empty string as False. When you pass None to your function, it evaluates to:

None == None and '' or None

which (effectively) becomes:

True and False or None

then:

False or None

and finally:

None

One solution would be:

lambda x: x if x is not None else ''

If you know x will be either a string or None, then you can leverage the fact that None is also a False value in Python:

lambda x: x or ''
Daniel Stutzbach