177
votes

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)
16
I like your original syntax. I think it's already quite clear and easy to read.GuiSim
@GuiSim: I might be biased, but my answer reads almost like a normal English sentence...SilentGhost
"If s is None, then return an empty string; otherwise, return [string of] s." The code from the question reads like a normal English sentence too.Roger Pate
a) If the string s came from a dict lookup where the key was not found, then use dict.get(key, '')smci
b) If you only want this string-conversion for output formatting (e.g. for print), then you can directly do '... {}'.format(dict.get(1))`smci

16 Answers

104
votes

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)
158
votes
def xstr(s):
    return '' if s is None else str(s)
151
votes

Probably the shortest would be str(s or '')

Because None is False, and "x or y" returns y if x is false. See Boolean Operators for a detailed explanation. It's short, but not very explicit.

102
votes

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) # -> ''
63
votes

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

15
votes
def xstr(s):
   return s or ""
10
votes

Functional way (one-liner)

xstr = lambda s: '' if s is None else s
10
votes

A neat one-liner to do this building on some of the other answers:

s = (lambda v: v or '')(a) + (lambda v: v or '')(b)

or even just:

s = (a or '') + (b or '')
6
votes
def xstr(s):
    return {None:''}.get(s, s)
6
votes

UPDATE:

I mainly use this method now:

some_string = None
some_string or ''

If some_string was not NoneType, the or would short circuit there and return it, otherwise it returns the empty string.

OLD:

Max function worked in python 2.x but not in 3.x:

max(None, '')  # Returns blank
max("Hello", '') # Returns Hello
4
votes

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

xstr = lambda s: s is not None and s or ''
2
votes

If it is about formatting strings, you can do the following:

from string import Formatter

class NoneAsEmptyFormatter(Formatter):
    def get_value(self, key, args, kwargs):
        v = super().get_value(key, args, kwargs)
        return '' if v is None else v

fmt = NoneAsEmptyFormatter()
s = fmt.format('{}{}', a, b)
1
votes
def xstr(s):
    return s if s else ''

s = "%s%s" % (xstr(a), xstr(b))
1
votes

We can always avoid type casting in scenarios explained below.

customer = "John"
name = str(customer)
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + name

In the example above in case variable customer's value is None the it further gets casting while getting assigned to 'name'. The comparison in 'if' clause will always fail.

customer = "John" # even though its None still it will work properly.
name = customer
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + str(name)

Above example will work properly. Such scenarios are very common when values are being fetched from URL, JSON or XML or even values need further type casting for any manipulation.

0
votes

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 '')
-4
votes

Use F string if you are using python v3.7

xstr = F"{s}"