为什么`str.format()`忽略其他/未使用的参数?

Mar*_*nen 12 python string string-formatting python-3.x

我看到"为什么不join()自动将其参数转换为字符串?" 接受的答案让我思考:既然

显式优于隐式.

错误不应该默默地传递.

为什么str.format()忽略额外/未使用(有时是意外传递)的参数?对我来说,它看起来像是一个无声地传递的错误,它肯定不是明确的:

>>> 'abc'.format(21, 3, 'abc', object(), x=5, y=[1, 2, 3])
'abc'
Run Code Online (Sandbox Code Playgroud)

其实,这导致我的朋友一个问题与os.makedirs(path, exist_ok=True)仍然引发错误,即使该文档os.makedirs()称,exist_ok=True即使不会引发错误path已经存在.原来他只是有一个嵌套函数调用的长行,并且exist_ok被传递到嵌套.format()调用而不是os.makedirs().

Mar*_*ers 13

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

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

换句话说,选择是有意的,因为允许更多参数而不是转换的实际原因.请注意String.Formatter,出于同样的原因,启发Python PEP 的C#实现也是如此.

并非PEP这一部分的讨论是明确的; Guido van Rossum在某些时候试图解决这个问题:

如果位置参数太少或太多,或者关键字丢失或未使用,PEP会对发生的情况保持沉默.遗失的应该是错误; 我不确定冗余(未使用)的那些.一方面抱怨这些让我们更加确定格式字符串是正确的.另一方面,有一些用于传递大量关键字参数的用例(例如,简单的网页模板可以使用**dict传递一组固定的变量).即使在i18n(翻译)应用程序中,我也可以看到允许未使用参数的有用性

PEP作者回答说他们在这一点上仍未决定.

对于必须为未使用的参数引发异常的用例,您应该为string.Formatter()该类创建并为其提供实现Formatter.check_unused_args(); 默认实现什么都不做.这当然不会帮助你朋友的情况str.format(*args, **kwargs)而不是你使用的情况Formatter().format(str, *args, **kwargs).我相信在某些时候,我们的想法是你可以用str.format()自定义实现替换使用的格式化程序,但这种情况从未发生过.

如果你使用flake8linter,那么你可以添加flake8-string-format插件来检测明显的情况,你传入一个未被格式字符串使用的显式关键字参数.

  • 对我而言,它只是觉得禅宗就像美国的法律:它拥有一切,你可以通过引用它的不同部分来证明任何事情.Imo*"实用性节拍纯度"*也适用于另一个问题,`str.join()`实际上应该将所有内容转换为字符串,因为这只是实用的.如果你用短划线加入"1"和"2",除了"1-2"之外还应该做什么.虽然这是另一个问题的讨论...... (4认同)
  • @SkamahOne:您可以自由地与Python核心开发人员合作. (4认同)
  • @MarkusMeskanen:同样在禅宗:*虽然实用性胜过纯洁.*有很好的实际理由不在这里提出异常.我现在正在通过最初的PEP讨论来找到具体的决定. (3认同)
  • @MarkusMeskanen:禅是*准则*,而不是法律.更好的是,它开始是一个*笑话*.这是一种哲学,而不是具有约束力的文件. (3认同)
  • 参考[你在另一个问题的答案激发了我提出这个问题](http://stackoverflow.com/questions/22152668/why-doesnt-join-automatically-convert-its-arguments-to-strings-when- would-yo/22152693#22152693),这个案子有什么不同?`.format()`的行为可以隐藏错误(就像我朋友的情况一样),而`.format()`只是忽略你传递给它的一切.Imo它甚至比`join()`更糟糕. (2认同)