python 字符串格式中的可选 space

optional space in python string formatting

假设我有 3 个 python 字符串,我可以用 2 个分隔的 space 格式化所有 3 个字符串,如下所示:

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.

我知道我可以使用不同的函数和条件表达式来通过代码进行格式化,例如 in

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

或选择不同的格式字符串

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

基于m的长度

我的问题是可以使用 格式化字符串 来完成吗? (例如,如果其参数不为空,将用 1 space 填充的一些格式修饰符)。

我不确定这是否可以通过格式化字符串来完成。

我会用 python string join 来做。

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(...) 将它们与 space 连接在一起。

不确定是否很方便,但有一种方法,根据字符串的 "truth" 值生成或不生成 space:

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

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

结果:

hello my world

现在将 m 设置为空字符串,您将得到

hello world

我认为单独使用格式化字符串是不可能的。

如果您必须使用格式字符串,您可以在应用格式后使用 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

这就是你想要的吗?

你可以使用新样式字符串格式的Parametrized formats,但你仍然需要自己测试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'

我将接受@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))

具有 "optionally (if m then) align it to the right and pad with one additional space to its left" 或

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

具有 "optionally (if m then) align it to the left and pad with one additional space to its right"

的语义

类似的变体可能有助于货币符号的可选格式 例如

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'

也许这可以使用此处描述的方法来实现: