命名参数的字符串格式化?

158

我知道这是一个非常简单的问题,但我不知道如何在谷歌上搜索它。

我该怎么做?

print '<a href="%s">%s</a>' % (my_url)

那么如何使 my_url 被使用两次?我猜我必须给 %s "命名",然后在 params 中使用一个字典,但我不确定正确的语法是什么?


只是提醒一下,我知道我可以在 params 中两次使用 my_url,但这不是重点 :)


问题的标题有点误导人。这与打印语句无关,只与字符串插值的工作方式有关。 - Greg Ball
当你不知道如何在谷歌中找到答案时,可以使用这里的搜索:http://python.org/doc/。它比谷歌更好的一个重要原因是。 - S.Lott
1
@S.Lott 这真的很有帮助 /s - mpen
8个回答

236
print '<a href="%(url)s">%(url)s</a>' % {'url': my_url}

3
我更喜欢使用kwargs创建字典:'%(url)s' % dict(url=my_url)其中,my_url 是您要插入到链接中的URL。 - schlamar
11
我想知道为什么你更喜欢那个schmlamar?相比于OP通常使用的字典声明,我不会很容易地知道那是什么意思。 - GreenAsJade
1
该**文档**没有指明引入的时间,因此很可能在所有Python 2版本中都存在。 - Evgeni Sergeev
2
如果可以的话,请使用format(),它在更多的地方效果更好。如果必须使用%,则使用它。 - uchuugaka

105

在Python 2.6+和Python 3中,你可能选择使用更新的字符串格式化方法。

print('<a href="{0}">{0}</a>'.format(my_url))

这可以避免重复使用参数,或者

print('<a href="{url}">{url}</a>'.format(url=my_url))

如果你想要命名参数。

print('<a href="{}">{}</a>'.format(my_url, my_url))

这种格式化方式是严格按位置顺序进行的,但需要注意的是,format()函数的参数遵循Python规则,即未命名参数必须先出现,然后是命名参数,接着是*args(类似于列表或元组的序列),最后是*kwargs(如果你知道怎么做,可以使用字符串键的字典)。 插值点首先通过替换其标签处的命名值来确定,然后从剩余部分进行按位置匹配。 因此,你也可以这样做...

print('<a href="{not_my_url}">{}</a>'.format(my_url, my_url, not_my_url=her_url))

但不包括这个...

print('<a href="{not_my_url}">{}</a>'.format(my_url, not_my_url=her_url, my_url))

1
很高兴看到影响从++转向#。 - cod3monk3y
3
然而,上述方法并不适用于“命名字符串格式化”,它只适用于位置字符串格式化。因此,这并没有真正回答这个问题。 - jaapz
1
"{arg1}".format(arg1="arg!") 这种命名格式适用于 Python 3.5,而更简洁的 f"literal {arg1}" 是 Python 3.6 或更新版本中的新创新,据我所知。 - MarkHu
1
考虑到包括非位置语法print('<a href="{url}">{url</a>}'.format(url=my_url))在内的此答案的更改,@jaapz的评论已不再有效。 这在Python 2和3中都可以很好地工作。 - Danila Vershinin
@uchuugaka 您添加的示例,即使是 "you can do this" 的示例,也有两个占位符但三个参数。您需要删除第二个 my_url。(尽管它似乎仍然可以工作——Python 会悄悄地忽略它,这对我来说是一个惊喜。) - Arthur Tacca
不是完全被忽略了。请重新阅读我的解释。 - uchuugaka

48

Python 3.6+版本中的解决方案

Python 3.6引入了字面字符串格式化,因此您可以在字符串内部格式化命名参数,而无需重复使用外部的命名参数:

print(f'<a href="{my_url:s}">{my_url:s}</a>')

这将评估my_url,所以如果它未定义,你将得到一个NameError。实际上,你可以写任意的Python表达式来代替my_url,只要它能够求值为字符串(因为有了:s格式化代码)。如果你想要对可能不是字符串的表达式结果进行字符串表示,可以用!s替换:s,就像常规的预字面字符串格式化一样。
有关字面字符串格式化的详细信息,请参阅PEP 498,这是它首次引入的地方,以及PEP 701,其中扩展了允许的语法(从Python 3.12开始)。

2
那个PEP似乎没有涵盖所有格式化程序;我认为它们与在此处记录的str.format相同:https://docs.python.org/3.4/library/string.html#formatstrings - mpen

7

您会迷上这种语法。

C# 6.0和EcmaScript开发人员也熟悉这种语法。

In [1]: print '{firstname} {lastname}'.format(firstname='Mehmet', lastname='Ağa')
Mehmet Ağa

In [2]: print '{firstname} {lastname}'.format(**dict(firstname='Mehmet', lastname='Ağa'))
Mehmet Ağa

5

对于构建HTML页面,您应该使用模板引擎而不是简单的字符串插值。


我正在使用Django,但这将进入一封电子邮件。 - mpen
2
Django的模板引擎也可能是您制作电子邮件的理想工具。 - Mike Graham
6
为什么不使用Django模板的render()方法生成电子邮件正文呢?没有规定你必须将模板输出提供给HttpResponse()。Django非常灵活。 - Mike DeSimone
1
@Mike:我 认为 Django 也可能有解决这个问题的方法,但我还没有找到它 :p 我可能会将我的电子邮件移入模板中!谢谢。也许我比较 "tarded",但我发现在某些方面它相当严格。 - mpen
2
@随机浏览这些评论的人:在这里可以找到更详细的信息,以了解如何执行此操作http://www.rossp.org/blog/2006/jul/11/sending-e-mails-templates/。 - mpen
2
在评论问题时,您应该使用评论而不是答案。 - suriv

4
另一种选择是使用format_map
print('<a href="{s}">{s}</a>'.format_map({'s': 'my_url'}))

2

除了使用字典的方式,了解下面的格式也可能会有用:

print '<a href="%s">%s</a>' % (my_url, my_url)

这里有点多余,使用字典的方式当然更不容易出错,但是仍然可以使用元组进行多个插入。第一个%s被替换为元组中的第一个元素,第二个%s被替换为元组中的第二个元素,以此类推,每个元素都被替换。


我刚才制止了一个人建议这个 :) 他删除了他的帖子。现在我感觉有点不好。是的,我知道我可以这样做,但那只是不是我想要的。正如你所说,这是多余的,而且my_url实际上是一个函数调用,我不想让它被评估两次。两次也还好,但可能会达到20次:) - mpen
5
我会尽力进行翻译,保持原意并使其更加易于理解。以下是需要翻译的内容:我想我会保留我的代码,以防万一有助于其他人。即便字典方式可能是最佳选择,但对于冗余,(get_my_url(), )*20 仅调用函数一次,并重复 20 次。 - Ponkadoodle

1
我推荐使用这个语法。
dictionary_of_string_values = {
                               "my_text" : "go to w3schools",
                               "my_url" : "https://www.w3schools.com",
                               }

print ('<a href="{my_url}">{my_text}</a>'.format(**dictionary_of_string_values))

当你需要使用大量占位符格式化一个字符串时,它非常有用。

你还可以像这样使其更短:

print ('<a href="{my_url}">{my_text}</a>'.format(
                             **{
                               "my_text" : "go to w3schools",
                               "my_url" : "https://www.w3schools.com",
                               }
                            )
                        )

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