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.