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


156

Який самий ідіоматичний спосіб зробити наступне?

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

s = xstr(a) + xstr(b)

update: Я включаю пропозицію Tryptich використовувати str (s), що робить цю рутинну роботу для інших типів, крім рядків. Мене дуже вражає лямбдаська пропозиція Віная Саджіпа, але я хочу зробити свій код порівняно простим.

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, де ключ не знайдений, тоді використовуйтеdict.get(key, '')
— smci

б) Якщо ви хочете, щоб ця конвертація рядків була лише для форматування виводу (наприклад, для друку), ви можете безпосередньо зробити формат '... {}'. (dict.get (1)) `
— smci

Відповіді:


94

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

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

Я зберігаю інше, але дякую за наконечник str (s), щоб можна було обробити кілька типів. приємно!
— Марк Гаррісон

11
Або просто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.
— Лінн

Дякую @Lynn, ти маєш рацію. Я зрозумів свою провину. Але я знаю (або припускаю) sзавжди тип 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 - ніхто інший ""
— Бер,

5
@Ber: Я б тримав це так, як є, щоб уникнути подвійного негативу.
— Нікіл Челлі

8
Це хороший приклад того, як .. and .. or ..виходить з ладу і чому віддається перевага. Тут є два тонких помилки s is not None and s or ''.

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

110

Напевно, найкоротший був би str(s or '')

Оскільки None є неправдивим, а "x або y" повертає y, якщо x є хибним. Докладні пояснення див. У розділі " Булові оператори" . Це коротко, але не дуже явно.


1
це так чудово, дякую! Ніколи не думав використовувати orцей спосіб
— user25064

15
Це не працює, якщо sце значення 0, 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 тощо, як хибний. Також використовує той факт, що або оператор повертає перший елемент, що є істинним, або останній елемент, наданий або (або групам орі). Також для цього використовуються лямбда-функції. Я дав би вам +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 (що не є оригінальним рядковим запитанням, але оновленим.)
— Оновлення

@Oddthinking 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" "if s is None other s" теж є
— онлайновим

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! 😀
— Віллем ван Кетвіч

1
Зауважте, що Falseі порожній список також буде перетворений на "".
— Нік О'Лай

те ж саме і 0т. д.
— Вальтер Трос

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

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

14
Не надто повільний (додаткова конструкція та пошук), і важче читати. Досить непітонічний.
— Триптих

Ти маєш рацію. Це досить приємно, але це дозволяє уникнути умовного стрибка в байт-коді python.
— тобідоп

4
Виклик функції get () передбачає принаймні один додатковий умовний стрибок.
— Триптих

1
Я не зможу сказати, що це робити, не знаючи питання і не піднімаючи погляд get.
— Даріо

5

Я використовую функцію max:

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

Працює як шарм;) Просто поставте рядок у перший параметр функції.


5
Це працює тому, що 'str'> 'NoneType' і є специфічним для CPython. З посібника : "Об'єкти різних типів, крім номерів, упорядковуються за їх назвами типів". Крім того, це не буде працювати в Python 3000, оскільки порівняння між типами більше не дозволено (TypeError: нерозбірливі типи: str ()> NoneType ()). Див. Як Python порівнює рядки та int?
— plok

Добре знати спасибі, тому не дуже гарна ідея рухатися вперед із сумісним кодом python 3.x.
— radtek


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

У наведеному вище прикладі у випадку, якщо значення змінної замовника є "None", воно додатково отримує кастинг під час призначення "name". Порівняння в пункті "якщо" завжди буде невдалим.

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. Наприклад, порожні кортежі, списки та дикти перетворюються на порожні рядки, що не є тим, що вказано в ОП.
— Триптих

+є ідеально хорошим оператором для двох струн. Коли ви намагаєтеся використовувати його, щоб приєднатися до десятків, у вас виникли проблеми. Для двох це, мабуть, буде швидше, ніж інші варіанти; так чи інакше, це в шумі.
— kquinn

+1 для мене тому, що це саме те, що мені потрібно в моєму випадку: лямбда або функція для заміни одного оператора ( or) здається для мене трохи зайвим ... Я не маю випадків інших помилкових значень - або str, або None. Крім коментаря +оператора, який може залежати від конкретного сценарію і може знадобитися тестування, ця відповідь не заслуговує на -1
— міський

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.