Python字符串格式化中的可选空格

9
假设我有3个Python字符串,我可以像下面这样使用2个空格将它们分隔开来进行格式化:
h="hello"
m="my"
w="world"

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

或者使用
print("%s %s %s" % (h,m,w))

假设现在我确定h和w都有值,但m可能是一个空字符串。上面的两个代码片段将会得到"hello{two spaces here}world"。
我知道可以使用不同的函数和条件表达式来通过代码进行格式化,例如:
print(h+" " + m+(" " if len(m)>0 else "") + w)

或选择不同的格式化字符串

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

根据m的长度。

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


1
{btsdaf} - Jean-François Fabre
5个回答

5

不确定它是否非常方便,但有一种方法:根据字符串的“真实”值生成空格或不生成空格:

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

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

结果:

hello my world

现在将m设置为空字符串,你会得到
hello world

4

我不确定能否使用格式化字符串来完成此操作。

我会使用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(...)用一个空格将它们连接在一起。


2
{btsdaf} - cs95
2
{btsdaf} - Jean-François Fabre
{btsdaf} - Chris Charles
4
' '.join(filter(None, strings)) 也可以工作,并且对于这种情况更快。 - Martijn Pieters

2

我认为仅仅使用格式化字符串是不可能做到这一点的。

如果你必须使用格式化字符串,你可以使用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

您需要的是这个吗?


2

我将接受 @Jean-François Fabre 的答案,他基本上回答了我指定的问题,即(至少目前)没有仅使用字符串格式化的答案(即如果要格式化的变量只是h、m和w而不需要额外处理)。

然而,使用字符串上的布尔运算符的概念,如他的答案中所述,我认为我将使用:

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

这种方式的缺点是会让读者感觉有四个值正在被格式化(从技术上来说确实如此,但语义上并非如此),但我认为这里表达式的简短和简单克服了负面影响。

可通过使用@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))  

我可以帮助翻译一些关于IT技术的内容。以下是需要翻译的内容:

返回一个空字符串或$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://dev59.com/YWw15IYBdhLWcg3wO5WX#15975791

1
顺便说一下:https://meta.stackoverflow.com/questions/291764/is-mentioning-someones-username-in-an-answer-supposed-to-send-them-a-notification - Jean-François Fabre

0

您可以使用新样式字符串格式化的参数化格式,但仍需自行测试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'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接