【问题标题】:optional space in python string formattingpython字符串格式中的可选空格
【发布时间】:2017-10-25 07:53:08
【问题描述】:

假设我有 3 个 python 字符串,我可以用它们之间的 2 个分隔空格来格式化所有 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 个空格填充)。

【问题讨论】:

  • 我检查了文档,我认为你不能。

标签: python string-formatting


【解决方案1】:

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

【讨论】:

【解决方案2】:

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

我会用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)&gt;0] 创建一个仅包含非零长度字符串的列表。然后" ".join(...) 用空格将它们连接在一起。

【讨论】:

  • 虽然这个答案没有错误,但它并没有解决 OP 的问题:Can this be done using the formatting strings?
  • 除了" ".join([s for s in strings if len(s)&gt;0]) 糟透了:" ".join([s for s in strings if s]) 更像是pythonic
  • @cᴏʟᴅsᴘᴇᴇᴅ 完全同意,我看不到纯格式的方法,但我不想说这是不可能的。
  • ' '.join(filter(None, strings)) 也可以工作,并且在这种情况下更快。
【解决方案3】:

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

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

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

结果:

hello my world

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

hello world

【讨论】:

    【解决方案4】:

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

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

    这就是你所追求的吗?

    【讨论】:

      【解决方案5】:

      您可以使用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'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-20
        相关资源
        最近更新 更多