用一个变量格式化多个 %s

Formatting multiple %s with a single variable

我有一个 %s 数量未知的字符串,需要使用单个字符串进行格式化。

例如,如果我有字符串 "%s some %s words %s" 并想用单词 house 格式化它,它应该输出 "house some house words house"

执行以下操作会出现错误:

>>> "%s some %s words %s" % ("house")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: not enough arguments for format string

所以,我决定执行以下操作,虽然可行,但对于这样一个简单的问题来说似乎过于复杂。

var = "house"
tup = (var,)
while True:
    try:
        print "%s some %s words %s" % tup
        break
    except:
        tup += (var,)

是否有更 pythonic 的方式来做到这一点?

如果你确定你要替换%s,你可以这样做:

var = "house"
tup = (var,)
txt = "%s some %s words %s"

print txt % (tup * txt.count("%s"))

但更好的解决方案是使用 str.format(),它使用不同的语法,但允许您按编号指定项目,因此您可以重复使用它们:

var = "house"
txt = "{0} some {0} words {0}"

print txt.format(var)

为什么不使用 format

"{0} some {0} words {0}".format("house")

这里有几个选项:

格式化字符串(和 Formatter class)

使用str.format 是最pythonic 的方式并且非常易于阅读。两种风格都受欢迎:

位置参数

'{0} some {0} words {0}'.format('house')

命名参数

'{word} some {word} words {word}'.format(word='house')

您在评论中提到由于其他遗留代码而保留原始格式字符串。你可以像这样破解:

'%s some %s words %s'.replace('%s', '{0}').format('house')

(我不推荐它,但您可以通过在替换调用中使用 'house' 而不是 '{0}' 来 "short circuit" 这个想法行。)

也就是说,我真的认为首先更改模板字符串是一个更好的主意。

模板字符串

在浏览了 string 文档后,又想到了一个替代方案:较旧的 string.Template class。默认情况下,它替换基于 $ 的值,但您可以 subclass 它覆盖定界符。例如:

class MyTemplate(Template):
    """
    Overriding default to maintain compatibility with legacy code.
    """
    delimiter = '%'


t = MyTemplate('%s some %s words %s')
t.substitute(s='house')

请记住,这不太常见,但您可以编写一次并在每次使用这样的字符串时重新使用它(假设只有一个输入值被替换)。至少写一次Pythonic!

文字字符串插值

在Python 3.6 中,Ruby-style string interpolation 是另一个社区尚未达成共识的选项。例如:

s = 'house'
f'{s} some {s} words {s}'