необязательное пространство в форматировании строк python

Предположим, у меня есть 3 строки python, и я могу отформатировать все 3 из них с 2 разделяющими пробелами между ними, как в следующем:

h="hello"
m="my"
w="world"

print("{} {} {}".format(h,m,w))

или через

print("%s %s %s" % (h,m,w))

предположим теперь, что я уверен, что h и w имеют значения, но m может быть пустой строкой. Два фрагмента кода выше приведут к "hello{two speces here}world.

Я знаю, что могу использовать различные функции и условные выражения для форматирования по коду, например в

print(h+" " + m+(" " if len(m)>0 else "") + w)

или выберите другую строку форматирования

print(("{} {} {}" if len(m)>0 else "{}{} {}").format(h,m,w))

на основе длины м.

мой Q-это можно сделать с помощью строки форматирования ? (например, некоторый модификатор формата, который будет заполняться 1 пробелом, если его параметр не пуст).

5 ответов


не уверен, что это очень удобно, но есть способ, генерирующий пространство или нет в зависимости от значения "истинности" строк:

h="hello"
m="my"
w="world"

print("{}{}{}{}".format(h," "*bool(m),m,w))

результат:

hello my world

сейчас поставил m чтобы очистить строку, вы получаете

hello world

Я не уверен, что это можно сделать с помощью строк форматирования.

Я бы сделал это с python строка присоединиться.

strings = [h, m, w]
print " ".join([s for s in strings if len(s)>0])

внутренняя часть [s for s in strings if len(s)>0] создает список только со строками ненулевой длины. Тогда " ".join(...) соединяет их вместе с пробелом между ними.


Я считаю, что это невозможно с помощью строк форматирования в одиночку.

если вам нужно использовать строки форматирования, вы можете использовать модуль re, чтобы избавиться от дополнительных пробелов после применения форматирования:

    import re

    h="hello"
    m="my"
    w="world"

    p = re.compile('\s+')

    print p.sub(" ","{} {} {}".format(h,m,w))

что бы выход:

    hello my world

С пустой строкой:

    print p.sub(" ","{} {} {}".format(h,"",w))

выводит:

    hello world

это то, что вы после?


Я приму ответ @Jean-François Fabre, который в основном отвечает на мой вопрос, как я его указал, сказав, что (по крайней мере, сейчас) нет ответа на это используя только форматирование строк (т. е. если переменные, которые будут сформированы, просто h, m & w без дополнительной обработки).

однако, используя концепцию булевых операторов на строках, как в его ответе, я думаю, что буду использовать:

print("{}{}{} {}".format(h,m and " " ,m , w))

это имеет недостаток давать человеку читая его чувствуя, что формируются 4 значения (что имеет место технически, но не семантически), но я думаю, что краткость и простота выражений здесь преодолевают отрицательный аспект.

читаемость может быть еще улучшена с помощью параметризованных форматов, как предложено @Tsingyi, но с использованием следующего:

print("{}{pad}{} {}".format(h, m , w, pad = m and " "))

Примечание:
НА МОМЕНТ НАПИСАНИЯ СТАТЬИ НЕ РАБОТАЕТ СЛЕДУЮЩИЙ КОД:
Надеюсь, в будущем, возможно, мы могли бы сделать что-то подобное:

print("{}{: >?} {}".format(h,m,w))

с семантикой "необязательно (если m тогда) выровнять его справа и площадку с одним дополнительным пространством слева", или

print("{} {: <?}{}".format(h,m,w))

с семантикой "необязательно (если m тогда) выровняйте его слева и поместите с одним дополнительным пространством справа"

подобные варианты могут быть полезны для дополнительного форматирования символов валюты например,

print("{:$>?}{}".format(s))  

чтобы получить либо пустую строку, либо $123

одно последнее (длинное) Примечание: на в какой-то момент во время моего исследования этой проблемы я подумал, что смогу сделать что-то вроде этого:

def extend_string_formatting():
    try:
       '{:left-pad-if-not-empty}'.format('')
    except ValueError:
        original_formatter=str.__format__

        def extended_formatter(self, format):
            if (format == 'left-pad-if-not-empty'):
                return ' ' + self if self else ''
            return original_formatter(self, format)

        str.__format__=extended_formatter
extend_string_formatting()

но оказывается, что это приводит к:

Traceback (most recent call last):
  File "<input>", line 3, in extend_string_formatting
ValueError: Invalid format specifier
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 12, in extend_string_formatting
TypeError: can't set attributes of built-in/extension type 'str'

может быть, этого можно достичь, используя что-то вроде того, что описано здесь: https://stackoverflow.com/a/15975791/25412


можно использовать параметризованных форматы С Новым форматированием строки стиля, но вам все равно нужно проверить, является ли m пусто или не самостоятельно.

def fmt(h, m, w):
    return return '{}{:>{wd}} {}'.format(h, m, w, wd=len(m)+1 if m else 0)

>>> fmt('hello', 'my', 'world')
'hello my world'
>>> fmt('hello', '', 'world')
'hello world'