Python: самый идиоматический способ преобразования None в пустую строку?


156

Какой самый идиоматичный способ сделать следующее?

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

s = xstr(a) + xstr(b)

Обновление: я включил предложение Триптиха использовать str (s), что делает эту рутинную работу для других типов, кроме строк. Я очень впечатлен лямбда-предложением Vinay Sajip, но я хочу, чтобы мой код был относительно простым.

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

7
Мне нравится ваш оригинальный синтаксис. Я думаю, что это уже довольно ясно и легко читается.
GuiSim

1
@GuiSim: Я могу быть предвзятым, но мой ответ читается почти как обычное английское предложение ...
SilentGhost

1
«Если s равно None, вернуть пустую строку; в противном случае вернуть [string of] s.» Код из вопроса читается как обычное английское предложение тоже.

а) Если строка sбыла получена из поиска, где ключ не был найден, используйтеdict.get(key, '')
команду

б) Если вам нужно это преобразование строк только для форматирования вывода (например, для печати), то вы можете напрямую выполнить '... {}'. format (dict.get (1)) `
smci

Ответы:


94

Если вы действительно хотите, чтобы ваша функция работала как str()встроенная, но возвращала пустую строку, когда аргумент None, сделайте это:

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

Я сохраняю остальное, но спасибо за подсказку str (s), чтобы можно было обрабатывать несколько типов. отлично!
Марк Харрисон

12
Или простоxstr = lambda s: '' if s is None else str(s)
Майкл Миор

2
Я люблю печатать if not s:вместоif s is None
guneysus

6
@guneysus Они не одинаковы: not False == Trueно False is None == False.
Линн

Спасибо @ Линн, ты прав. Я понял свою ошибку. Но я знаю (или предполагаю) sвсегда a в типе str / unicode или None. Да, Falseэто ценность, но я предпочитаю этот способ, который спасает мою клавиатуру и глаза;)
guneysus

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

3
Этот синтаксис был введен в 2.5; для более ранних версий Python вы можете использовать return s is not None and s or ''.
Бен Бланк

8
Я бы перевернул это, чтобы подчеркнуть более комменсальный случай: вернуть s, если s не None else ""
Ber

5
@Ber: я бы оставил все как есть, чтобы избежать двойного негатива.
Nikhil Chelliah

8
Это хороший пример того, как .. and .. or ..терпит неудачу, и почему предпочтение отдается if-else. Есть две тонкие ошибки в s is not None and s or ''.

1
return '' if not s else str(s)
Икбал

110

Вероятно, самый короткий будет str(s or '')

Потому что None равно False, и «x or y» возвращает y, если x равно false. Посмотрите Булевы Операторы для подробного объяснения. Это коротко, но не очень явно.


1
это так здорово, спасибо! Никогда не думал об использовании orэтого способа
user25064

15
Это не работает, если s0, False или любое ложное значение
wisbucky

4
Ну, это не упомянуто в требовании оперы, поэтому я не вижу твоей точки зрения здесь.
Дорвак

2
@dorvak ОП достаточно ясно указывает на требование, что вывод должен быть ''iff s is None. Все остальные входные данные должны возвращаться s(или str(s)в пересмотренном запросе).
StvnW

2
@fortea: это не сработает. Если sэто так None, результат xstr()должен быть пустой строкой, но str(None)дает строку "None", которая является тем, что возвращается (поскольку строка "None"не является ложным значением.
dreamlax

97

Если вы знаете, что значение всегда будет либо строкой, либо 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) # -> ''

1
безусловно, самый питонический. Использует тот факт, что python рассматривает None, пустой список, пустую строку, 0 и т. Д. Как ложные. Также используется тот факт, что оператор or возвращает первый элемент true или последний элемент, переданный or или (или группам ors). Также это использует лямбда-функции. Я бы дал вам +10, но, очевидно, это не позволит мне.
Мэтт

11
Это преобразует 0 и False (и все остальное, которое оценивается как False при передаче в bool ())
Аркадий

9
Я не думаю, что это "безусловно самый питонический". Это распространенная идиома в других языках, и я не думаю, что это неправильно использовать в Python, но условные выражения были введены именно для того, чтобы избежать подобных трюков.
Роберто Бонваллет

2
Это делает [], {}и т.д. дают тот же результат , как None, который не желательно. xstr(False), в частности, должно быть "False"вместо "". Злоупотребление лямбдами - плохой пример, используйте его, def xstr(s): return s or ""если хотите, чтобы все было в одной строке.

5
Обратите внимание, что вначале я уточнил свой ответ следующим образом: «Если вы знаете, что значение всегда будет либо строкой, либо« Нет »».
Vinay Sajip

59

return s or '' будет работать отлично для вашей заявленной проблемы!


4
Стоит отметить, что это даст другой результат, когда s имеет значение False или 0 (что не является исходным строковым вопросом, а обновленным).
Нечетное размышление

@ Нечетное мышление s = Falseили s = 0, скорее всего, это крайний случай в его использовании, и его можно легко смягчить, написав это какreturn str(s or '')
Виллем ван

@WillemvanKetwich: Это та же проблема: s (False) должен возвращать «False», а не «». s (0) должен возвращать '0', а не ''. Аналогично для объекта, который определяет __bool__ или __nonzero__.
Странная мысль

@ Странно, я понимаю твою точку зрения. В любом случае, если он используется исключительно для строковых объектов, таких как в вопросе OP, это не должно быть проблемой.
Виллем ван

@WillemvanKetwich: Посмотрите на обновленный вопрос и предостережение в моем комментарии - это было рассмотрено,
странное мышление


8

Функциональный способ (однострочник)

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

1
"def xstr (s): return '', если s - это None else s" также является встроенным, python не так строг с
пробелами

2
Это не настоящий однострочный текст, это просто написано в одной строке g
Дарио

1
в каком смысле это не настоящий лайнер? проверьте в вашем интерпретаторе - это не синтаксическая ошибка. для всех намерений и целей это более реально, чем лямбда ^ _ ^
SilentGhost

2
PEP 8 видов, которые вы должны использовать def вместо присвоения лямбда-переменной. Единственное реальное преимущество лямбды в том, что вы можете писать как часть выражения (например, передавая в другую функцию), и это преимущество теряется в таком коде. Я тоже делал это до тех пор, пока не заметил, что def можно записать в одну строку, а затем PEP 8 показал мне путь. ВСЕГДА следуйте за богами питонов.
Парень

8

Аккуратный однострочник, чтобы сделать это здание на некоторых из других ответов:

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

или даже просто:

s = (a or '') + (b or '')

Зачем вообще упоминать (lambda v: v or '')?
Tvde1

Почему нет? 2 подсказки по цене 1! W
Виллем ван

1
Пожалуйста, имейте в виду, что Falseи пустой список также будет превращен в ''.
Ник О'Лай,

то же самое 0и т. д.
Уолтер Тросс

6
def xstr(s):
    return {None:''}.get(s, s)

Я думаю, это довольно питонично - как насчет этого: "xstr = lambda s: {None: ''}. Get (s, s)" - сводит все это к одной строке.
Юрген

14
Неоправданно медленный (дополнительная конструкция и поиск) и труднее читать. Довольно не пифонично.
Триптих

Ты прав. Это довольно забавно, но избегает условного перехода в байт-коде Python.
Tobidope

4
Вызов функции get () подразумевает как минимум один дополнительный условный переход.
Триптих

1
Я не смогу сказать, что это должно делать, не зная вопроса или не глядя вверх get.
Дарио

5

Я использую функцию Макс:

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

Работает как шарм;) Просто поместите вашу строку в первый параметр функции.


5
Это работает, потому что 'str'> 'NoneType' и зависит от CPython. Из руководства : «Объекты разных типов, кроме номеров, упорядочены по именам типов». Кроме того, это не будет работать в Python 3000, поскольку сравнение между типами больше не разрешено (TypeError: неупорядоченные типы: str ()> NoneType ()). Посмотрите, как Python сравнивает строку и int?
plok

Полезно знать, спасибо, так что не очень хорошая идея двигаться вперед с кодом, совместимым с Python 3.x.
Радтек


2

Если речь идет о форматировании строк, вы можете сделать следующее:

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
def xstr(s):
    return s if s else ''

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

5
Это вернет пустую строку для всех ложноподобных значений, а это не то, о чем просил автор.
Триптих

1

Мы всегда можем избежать приведения типов в сценариях, описанных ниже.

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

В приведенном выше примере в случае, когда значение переменной customer равно None, оно далее получает приведение при присвоении имени. Сравнение в предложении if всегда будет неудачным.

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)

Приведенный выше пример будет работать правильно. Такие сценарии очень распространены, когда значения выбираются из URL, JSON или XML, или даже значения требуют дальнейшего приведения типов для любых манипуляций.


0

Используйте оценку короткого замыкания:

s = a or '' + b or ''

Поскольку + не очень хорошая операция со строками, лучше использовать строки формата:

s = "%s%s" % (a or '', b or '')

2
Это также преобразует 'a' в пустые строки для всех ложноподобных значений, а не только для None. Например, пустые кортежи, списки и тексты будут преобразованы в пустые строки, что не является указанием OP.
Триптих

+это очень хороший оператор для двух строк. Когда вы пытаетесь использовать его, чтобы присоединиться к десяткам, у вас возникают проблемы. Для двоих это, вероятно, будет быстрее, чем другие варианты; в любом случае, это в шуме.
Kquinn

+1 для меня, потому что это именно то, что мне нужно в моем случае: лямбда или функция для замены одного оператора ( or) кажется для меня излишним ... У меня нет случаев других ложных значений - либо str, либо None. За исключением комментария об +операторе, который может зависеть от конкретного сценария и может потребовать бенчмаркинга, этот ответ не заслуживает -1
городской

-3

Используйте строку F, если вы используете Python v3.7

xstr = F"{s}"

1
Это неправильно и возвращает строку, 'None'если sесть None.
Лоуренс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.