78

情况1:

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

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

案例二:

"{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'

我的问题是它为什么起作用以及在这种情况下命名参数的用途是什么。

4

2 回答 2

129

Named replacement fields (the {...} parts in a format string) match against keyword arguments to the .format() method, and not positional arguments.

Keyword arguments are like keys in a dictionary; order doesn't matter, as they are matched against a name.

If you wanted to match against positional arguments, use numbers:

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

In Python 2.7 and up, you can omit the numbers; the {} replacement fields are then auto-numbered in order of appearance in the formatting string:

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

The formatting string can match against both positional and keyword arguments, and can use arguments multiple times:

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

Quoting from the format string specification:

The field_name itself begins with an arg_name that is either a number or a keyword. If it’s a number, it refers to a positional argument, and if it’s a keyword, it refers to a named keyword argument.

Emphasis mine.

If you are creating a large formatting string, it is often much more readable and maintainable to use named replacement fields, so you don't have to keep counting out the arguments and figure out what argument goes where into the resulting string.

You can also use the **keywords calling syntax to apply an existing dictionary to a format, making it easy to turn a CSV file into formatted output:

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)

Here, picture, link, description and price are all keys in the row dictionary, and it is much easier to see what happens when I apply the row to the formatting string.

于 2013-07-27T08:30:50.460 回答
6

额外的好处包括

  • 不必担心参数的顺序。它们将位于字符串中的正确位置,如格式化程序中它们的名称所示。
  • 您可以将相同的参数放在一个字符串中两次,而不必重复该参数。例如"{foo} {foo}".format(foo="bar")给出'bar bar'

请注意,您也可以提供额外的参数而不会导致错误。所有这些在以下情况下特别有用

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

例如:

>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)
于 2019-09-12T08:02:46.727 回答