在 Python 中格式化字符串和命名参数

案例1:

"{arg1} {arg2}".format(10, 20)

它将给出 KeyError: 'arg1',因为我没有传递命名参数。

案例2:

"{arg1} {arg2}".format(arg1=10, arg2=20)

现在它将正常工作,因为我传递了命名参数。 打印 '10 20'

案例3:

而且,如果我传递错误的名称,它会显示 KeyError: 'arg1'

"{arg1} {arg2}".format(wrong=10, arg2=20)

但是,

案例4:

如果我在 错误的顺序中传递命名参数

"{arg1} {arg2}".format(arg2=10, arg1=20)

真的有用。

打印 '20 10'

我的问题是为什么它能工作,在这种情况下 命名论点有什么用。

92860 次浏览

命名的替换字段(格式化字符串中的 {...}部分)与 关键字参数匹配到 .format()方法,而不是 位置参数位置参数

关键字参数就像字典中的关键字; 顺序并不重要,因为它们与 姓名匹配。

如果要与 位置参数匹配,请使用数字:

"{0} {1}".format(10, 20)

在 Python 2.7及以上版本中,您可以省略这些数字; 然后,{}替换字段将按照格式化字符串中的外观顺序自动编号:

"{} {}".format(10, 20)

格式化字符串可以与两个位置 还有关键字参数匹配,并且可以多次使用参数:

"{1} {ham} {0} {foo} {1}".format(10, 20, foo='bar', ham='spam')

引自 格式字符串规范:

Field _ name本身以一个 Arg _ name开始,这个 Arg _ name或者是 一个数字或关键字。如果是数字,它指的是位置参数; 如果是关键字,它指的是命名关键字参数。

重点是我的。

如果要创建大型格式化字符串,那么使用命名替换字段通常更具可读性和可维护性,因此不必一直计算参数,并弄清楚哪个参数进入结果字符串的哪个位置。

您还可以使用 **keywords调用语法将现有字典应用于某种格式,这样就可以轻松地将 CSV 文件转换为格式化输出:

import csv


fields = ('category', 'code', 'price', 'description', 'link', 'picture', 'plans')
table_row = '''\
<tr>
<td><img src="{picture}"></td>
<td><a href="{link}">{description}</a> ({price:.2f})</td>
</tr>
'''


with open(filename, 'rb') as infile:
reader = csv.DictReader(infile, fieldnames=fields, delimiter='\t')
for row in reader:
row['price'] = float(row['price'])  # needed to make `.2f` formatting work
print table_row.format(**row)

在这里,picturelinkdescriptionprice都是 row字典中的键,简单多了将查看当我将 row应用到格式化字符串时会发生什么。

额外的好处包括

  • 不用担心争论的顺序。他们将落在正确的地方在字符串中,由他们的名字在格式化程序。
  • 你可以把 同一个参数在一个字符串中两次放进去,而不用重复参数

请注意,您可以提供额外的参数,而不会引起错误。 所有这些在以下情况下尤其有用

  • 稍后更改字符串格式化程序,更改次数较少,因此更改为 犯错误的可能性更小。如果它不包含新的命名参数,那么 format 函数仍然可以工作,而不需要更改参数,并将参数放在格式化程序中指定的位置。
  • 你可以拥有 共享一组参数的多个格式化程序字符串。在这种情况下,例如,您可以拥有一个包含所有参数的字典,然后根据需要在格式化程序中挑选它们。

例如:

>d = {"foo":"bar", "test":"case", "dead":"beef"}
>print("I need foo ({foo}) and dead ({dead})".format(**d))
>print("I need test ({test}) and foo ({foo}) and then test again ({test})".format(**d))
I need foo (bar) and dead (beef)
I need test (case) and foo (bar) and then test again (case)