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

Posted

技术标签:

【中文标题】在 Python 中格式化字符串和命名参数【英文标题】:format strings and named arguments in Python 【发布时间】:2013-07-27 13:52:46 【问题描述】:

案例 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'

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

【问题讨论】:

我认为它们只是为了便于阅读。 因为它是通过名称而不是位置来查找的...您认为命名参数是什么意思? 看起来您只是将 arg2 重命名为 arg1,反之亦然。换句话说,arg1 现在是 20 而不是 10,这就是为什么您会看到字符串中的第一个数字打印 20 而不是 10。要进行所需的测试,您只需将 args 及其值移动到新位置format() 调用,它会按照您期望的方式运行。这里没有什么不寻常的。 【参考方案1】:

命名替换字段(format string 中的 ... 部分)匹配 关键字参数.format() 方法,而不是 位置参数。 p>

关键字参数就像字典中的键;顺序无关紧要,因为它们与 name 匹配。

如果您想匹配 位置 参数,请使用数字:

"0 1".format(10, 20)

在 Python 2.7 及更高版本中,您可以省略数字;然后, 替换字段会按照在格式化字符串中出现的顺序自动编号:

" ".format(10, 20) 

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

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

引用format string specification:

field_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 到格式化字符串。

【讨论】:

它不仅更具可读性,在使用自然语言和“国际化”(i18n) 时也非常有用,有时您希望格式化消息的特定部分以不同的顺序以不同的语言出现. @torek:我什至不打算讨论模板中的不同排序;关键是每个插槽都指向一个特定的参数。您也可以在模板中以不同的顺序放置位置参数。【参考方案2】:

额外的好处包括

不必担心参数的顺序。它们将位于字符串中的正确位置,如格式化程序中它们的名称所示。 您可以将同一个参数放在一个字符串中两次,而不必重复该参数。例如。 "foo foo".format(foo="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)

【讨论】:

最后一个例子是我见过的 Python 中模板化字符串编码最方便的方法之一。特别是我不知道可以将字典参数传递给format,其中并非所有键都实际出现在格式字符串中。感谢您指出这一点!

以上是关于在 Python 中格式化字符串和命名参数的主要内容,如果未能解决你的问题,请参考以下文章

02python程序设计基础——字符串

格式化字符串未使用的命名参数[重复]

带命名参数的字符串格式

在Python中命名参数

python argparse命名位置参数?

Python入门-5函数:06参数类型-位置参数-默认值参数-命名参数-可变参数-强制命名参数