views:

1817

answers:

10

What is the most idiomatic way to do the following?

def xstr(s):
    if s is None:
        return ''
    else:
        return s

s = xstr(a) + xstr(b)

update: I'm incorporating Tryptich's suggestion to use str(s), which makes this routine work for other types besides strings. I'm awfully impressed by Vinay Sajip's lambda suggestion, but I want to keep my code relatively simple.

def xstr(s):
    if s is None:
        return ''
    else:
        return str(s)
+23  A: 
def xstr(s):
    return '' if s is None else str(s)
SilentGhost
I think this requires Python 2.6 or later. (But then, to a first approximation, so does sanity.)
Robert Rossney
works on 2.5 for me just fine.
SilentGhost
This syntax was introduced in 2.5; for earlier versions of Python, you can use `return s is not None and s or ''`.
Ben Blank
Is there a __future__ statement to enable it in 2.4?
Richard Levasseur
I'd turn it around to emphasize the more commen case: return s if s is not None else ""
Ber
@Ber: I would keep it as is, to avoid a double negative.
Nikhil Chelliah
This is a good example of how `.. and .. or ..` fails and why if-else is preferred. There're two subtle bugs in `s is not None and s or ''`.
Roger Pate
A: 
def xstr(s):
    return s if s else ''

s = "%s%s" % (xstr(a), xstr(b))
phillc
This will return an empty string for all false-like values, which is not what the poster asked for.
Triptych
+3  A: 
def xstr(s):
    return {None:''}.get(s, s)
tobidope
I think, it is rather pythonic -- how about this one: "xstr = lambda s : {None:''}.get(s,s)" -- reduces the whole thing to a one-liner.
Juergen
Unnecessarily slow (extra dict construction and lookup), and harder to read. Pretty unpythonic.
Triptych
You're right. It's rather perlish but it avoids a conditional jump in python bytecode.
tobidope
The get() function call implies at least one additional conditional jump.
Triptych
I wouln't be able to say what this should do without knowing the question or looking up `get`.
Dario
Dario: how many language features (in any language) can you say what they do without already knowing them and without looking them up?
Roger Pate
+8  A: 

If you actually want your function to behave like the str() built-in, but return an empty string when the argument is None, do this:

def xstr(s):
    if s is None:
        return ''
    return str(s)
Triptych
I'm keeping the else, but thanks for the str(s) tip so multiple types can be handled. nice!
Mark Harrison
A: 

Functional way (one-liner)

xstr = lambda s: '' if s is None else s
Dario
"def xstr(s): return '' if s is None else s " is an on-liner too, python is not as strict with whitespaces after all
SilentGhost
It's no real one-liner, it's just written in one line *g*
Dario
in what sense it's not a real onliner? check in your interpreter - it's not a syntax error. for all intents and purposes it's way real than lambda ^_^
SilentGhost
A: 

Use short circuit evaluation:

s = a or '' + b or ''

Since + is not a very good operation on strings, better use format strings:

s = "%s%s" % (a or '', b or '')
sharjeel
ever heard of DRY?
SilentGhost
This also will convert 'a' to empty strings for all false-like values, not just None. For instance, empty tuples, lists, and dicts will convert to empty strings, which is not what the OP specified.
Triptych
`+` is a perfectly good operator for two strings. It's when you try to use it to join dozens that you have trouble. For two, it'll probably be *faster* than other options; either way, it's in the noise.
kquinn
+12  A: 

If you know that the value will always either be a string or None:

xstr = lambda s: s or ""

print xstr("a") + xstr("b") # -> 'ab'
print xstr("a") + xstr(None) # -> 'a'
print xstr(None) + xstr("b") # -> 'b'
print xstr(None) + xstr(None) # -> ''
Vinay Sajip
by far the most pythonic. Uses the fact that python treats None, an empty list, an empty string, 0, etc as false. Also uses the fact that the or statement returns the first element that is true or the last element given to the or (or groups of ors). Also this uses lambda functions.I would give you +10 but obviously it wont let me.
Matt
This will convert 0 and False (and anything else that evaluates to False when passed to bool())
scrible
I don't think it's "by far the most pythonic". It's a common idiom in other languages, and I don't think it's wrong to use it in Python, but conditional expressions where introduced precisely to avoid tricks like this.
Roberto Bonvallet
I don't think that was the reasoning behind conditional expressions. It's not particularly tricky, either - there's nothing all that special about it other than it's neat and tidy. I suggest only using it if you know that s is always a string or None - as I said in the introduction. If that's the case, this seems like the most compact way.
Vinay Sajip
This makes `[]`, `{}`, etc. give the same result as `None`, which isn't desired. `xstr(False)`, in particular, should be `"False"` instead of `""`. Abusing lambdas makes for a poor example, use `def xstr(s): return s or ""` ir you want to keep it all on one line.
Roger Pate
Note that I qualified my answer at the outset with "If you know that the value will always either be a string or None".
Vinay Sajip
+11  A: 

return s or '' will work just fine for your stated problem!

Alex Martelli
Worth noting that this will give a different result for when s is False or 0 (which isn't the original string question, but the updated one.)
Oddthinking
+2  A: 

Variation on the above if you need to be compatible with Python 2.4

xstr = lambda s: s is not None and s or ''
Peter Ericson
A: 
def xstr(s):
   return s or ""