ChatGPT解决这个技术问题 Extra ChatGPT

Python: most idiomatic way to convert None to empty string?

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

d
dorvak

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.


this is so great, thank you! Never thought of using or this way
This doesn't work if s is 0, False, or any falsy value
Well, that's not mentioned in the op's requirement, so I don't see your point here.
@dorvak The OP is quite explicit about the requirement that the output should be '' iff s is None. All other input should return s (or str(s) in the revised request).
@fortea: that won't work. If s is None, the result of xstr() should be an empty string, but str(None) gives the string "None", which is what is returned (since the string "None" is not a falsy value.
V
Vinko Vrsalovic
def xstr(s):
    return '' if s is None else str(s)

This syntax was introduced in 2.5; for earlier versions of Python, you can use return s is not None and s or ''.
I'd turn it around to emphasize the more commen case: return s if s is not None else ""
@Ber: I would keep it as is, to avoid a double negative.
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 ''.
return '' if not s else str(s)
K
Kenan Banks

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)

I'm keeping the else, but thanks for the str(s) tip so multiple types can be handled. nice!
Or simply xstr = lambda s: '' if s is None else str(s)
I love typing if not s: instead of if s is None
@guneysus They aren’t the same: not False == True but False is None == False.
Thanks @Lynn you are right. I realized my fault. But I know (or assume) s always a in str/unicode type or None. Yes, False is a value but I prefer this way that saves my keyboard and eyes ;)
V
Vinay Sajip

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

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.
This will convert 0 and False (and anything else that evaluates to False when passed to bool())
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.
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.
Note that I qualified my answer at the outset with "If you know that the value will always either be a string or None".
A
Alex Martelli

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


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 s = False or s = 0 would most likely be an edge case in it's use and could be easily mitigated by writing it as return str(s or '')
@WillemvanKetwich: That has exactly the same problem: s(False) should return 'False', not ''. s(0) should return '0', not ''. Likewise for an object that defines __bool__ or __nonzero__.
@Oddthinking I see your point. In any case, if it is used exclusively for string objects such as in the OP's question it shouldn't be an issue.
@WillemvanKetwich: Have a look at the updated question and the caveat in my comment - this has been covered,
K
Krystian Cybulski
def xstr(s):
   return s or ""

This returns '' for 0, [], {}, False and false-like values, which is not what the poster asked for.
just put str([...]) around s: def xstr(s): return str(s) or ""
D
Dario

Functional way (one-liner)

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

"def xstr(s): return '' if s is None else s " is an on-liner too, python is not as strict with whitespaces after all
It's no real one-liner, it's just written in one line g
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 ^_^
PEP 8 species that you should use def instead of assigning lambda to a variable. The only real advantage of lambda is that you can write as a part of expression(passing to another function for instance) and that advantage is lost in code like this. I used to do this too, until I noticed that def can be written in one line, and then PEP 8 showed me the way to go. ALWAYS follow the python gods.
W
Willem van Ketwich

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

Why even mention (lambda v: v or '')?
Why not? 2 tips for the price of 1! 😀
Please be aware that False and empty list will also be turned to ''.
same for 0, etc.
r
radtek

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

This works because 'str' > 'NoneType', and is CPython specific. From the manual: "Objects of different types except numbers are ordered by their type names". Also, this won't work in Python 3000, since inter-type comparison is no longer allowed (TypeError: unorderable types: str() > NoneType()). See How does Python compare string and int?
Good to know thanks, so not a good idea moving forward with python 3.x compatible code.
t
tobidope
def xstr(s):
    return {None:''}.get(s, s)

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.
Unnecessarily slow (extra dict construction and lookup), and harder to read. Pretty unpythonic.
You're right. It's rather perlish but it avoids a conditional jump in python bytecode.
The get() function call implies at least one additional conditional jump.
I wouln't be able to say what this should do without knowing the question or looking up get.
P
Peter Ericson

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

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

m
maciek

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)

p
phillc
def xstr(s):
    return s if s else ''

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

This will return an empty string for all false-like values, which is not what the poster asked for.
P
Pralhad Narsinh Sonar

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.


s
sharjeel

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

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.
+ 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.
+1 for me cause this is exactly what I need in my case: lambda or function to replace a single operator (or) seems a bit of an overkill for me... I dont have cases of other falsly values - either str or None. Other than the comment on the + operator, which might depend on specific scenario and might need benchmarking, this answer does not deserve a -1
g
guagay_wk

Use F string if you are using python v3.7

xstr = F"{s}"

This is wrong and returns the string 'None' if s is None.