为什么 `str.format()` 忽略 additional/unused 参数?

Why does `str.format()` ignore additional/unused arguments?

我看到 "Why doesn't join() automatically convert its arguments to strings?" and the accepted answer 让我想到:因为

Explicit is better than implicit.

Errors should never pass silently.

为什么 str.format() 忽略 additional/unused(有时不小心传递)参数?对我来说,它看起来像是一个默默传递的错误,而且它肯定不是明确的:

>>> 'abc'.format(21, 3, 'abc', object(), x=5, y=[1, 2, 3])
'abc'

这实际上导致我的朋友遇到一个问题 os.makedirs(path, exist_ok=True) 仍然会引发错误,即使 the docs for os.makedirs()exist_ok=True 即使 path 也不会引发错误已经存在。 原来他只是有一个长长的嵌套函数调用行,exist_ok 被传递给嵌套的 .format() 调用而不是 os.makedirs().

忽略未使用的参数可以为任意大小的字典或对象创建任意格式的字符串。

假设您想为您的程序提供让最终用户更改输出的功能。您记录了哪些 字段 可用,并告诉用户将这些字段放在字符串中的 {...} 槽中。然后最终用户可以创建模板字符串,其中 任何数量 正在使用的字段,包括 none, 没有错误

换句话说,这个选择是经过深思熟虑的,因为有实际原因允许比转换的参数更多。请注意,出于同样的原因,启发 Python PEP 的 C# String.Formatter 实现也是如此。

并不是说关于 PEP 这一部分的讨论是那么明确; Guido van Rossum 在某个时刻 tries to address this issue:

The PEP appears silent on what happens if there are too few or too many positional arguments, or if there are missing or unused keywords. Missing ones should be errors; I'm not sure about redundant (unused) ones. On the one hand complaining about those gives us more certainty that the format string is correct. On the other hand there are some use cases for passing lots of keyword parameters (e.g. simple web templating could pass a fixed set of variables using **dict). Even in i18n (translation) apps I could see the usefulness of allowing unused parameters

PEP 作者 responded 表示他们在这一点上仍未决定。

对于必须为未使用的参数引发异常的用例,您应该将 string.Formatter() class and provide an implementation for Formatter.check_unused_args() 子类化;默认实现什么都不做。这当然对您朋友使用 str.format(*args, **kwargs) 而不是 Formatter().format(str, *args, **kwargs) 的情况没有帮助。我相信在 某个时候 的想法是您可以用自定义实现替换 str.format() 使用的格式化程序,但这从未实现。

如果您使用 flake8 linter, then you can add the flake8-string-format plugin 来检测明显的情况,您传入的 explicit 关键字参数未被格式字符串使用。