使用百分号进行Python字符串格式化

22

我正尝试做完全如下所示的事情:

>>> x = (1,2)
>>> y = 'hello'
>>> '%d,%d,%s' % (x[0], x[1], y)
'1,2,hello'

然而,我的 x 非常长,超过了两个项目,所以我尝试了:

>>> '%d,%d,%s' % (*x, y)

但这是语法错误。没有像第一个示例那样进行索引,正确的方法是什么?


2
使用“str.format”是Pythonic的方法。 - Eli Korvigo
2
这是一个有争议的问题,是否更符合“Pythonic”的风格,但 str.format 方法调用允许您使用 *args 扩展。 - Anentropic
3个回答

24

str % .. 接受一个元组作为右操作数,因此你可以这样做:

>>> x = (1, 2)
>>> y = 'hello'
>>> '%d,%d,%s' % (x + (y,))  # Building a tuple of `(1, 2, 'hello')`
'1,2,hello'

您的代码应该在 Python 3 中运行,其中支持Additional Unpacking Generalizations,但不支持 Python 2.x:

>>> '%d,%d,%s' % (*x, y)
'1,2,hello'

2
实际上,扩展的可迭代解包不允许使用这种语法(Python3.4):>>> '%d,%d,%s' % (*x, y)。可能会在Python3.5的Additional Unpacking Generalizations中允许使用。但是,在当前版本中,会出现“SyntaxError: can use starred expression only as assignment target”的错误提示。 - Bakuriu
@Bakuriu,感谢您指出这一点。我已经相应地更新了答案。 - falsetru

12

也许可以看看str.format()

>>> x = (5,7)
>>> template = 'first: {}, second: {}'
>>> template.format(*x)
'first: 5, second: 7'

更新:

为了完整起见,我还包括了由PEP 448描述的其他解包通用性。扩展的语法是在 Python 3.5 中引入的,以下内容不再是语法错误:

>>> x = (5, 7)
>>> y = 42
>>> template = 'first: {}, second: {}, last: {}'
>>> template.format(*x, y)  # valid in Python3.5+
'first: 5, second: 7, last: 42'

在Python 3.4及以下版本中,如果您想在解包的元组后传递额外的参数,最好将它们作为命名参数传递:
>>> x = (5, 7)
>>> y = 42
>>> template = 'first: {}, second: {}, last: {last}'
>>> template.format(*x, last=y)
'first: 5, second: 7, last: 42'

这样可以避免需要在末尾构建一个新的包含额外元素的元组。


这应该写在注释里,而不是作为答案,除非你扩展它并展示如何使用 str.format() 来完成 OP 所尝试的操作。 - Cyphase
是的,我正在写那个,但太快了,不小心发布了一个答案。 - plamut
2
如何将此应用于我的先前示例?'{},{},{}'.format( *x,y )仍然无法工作? - Sait
1
'{1},{2},{0}'.format(y, *x )' - 位置参数扩展运算符必须放在所有其他位置参数之后 - 但是您可以使用一个技巧,在模板中标记占位符以更改顺序。 - plamut
1
@plamut 注意,PEP 448.format(*x, y) 进行了更改。 - Bakuriu
@Bakuriu 是的,我知道,但它只会在Python 3.5中引入(OP使用不同版本)。无论如何,感谢您提到它! - plamut

2
我建议您使用str.format而不是str %,因为它更加“现代化”,并且具有更好的功能集。话虽如此,您需要的是:
>>> x = (1,2)
>>> y = 'hello'
>>> '{},{},{}'.format(*(x + (y,)))
1,2,hello

如果您想了解format的所有酷炫功能(以及与%相关的一些功能),请参阅PyFormat


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