<p>函数接受<code>n</code>个参数。您提供了<code>m</code>。<code>n != m</code>。这可能是某个人代码中的一个bug,或者是某人对某个API的误解。另外,我认为我们不能就有意义的,有用的语义达成一致。多余的论点应该被忽略吗?这会让这些错误消失,而且“错误永远不会悄悄地过去”,这是不可接受的。类似地,为省略的参数提供一些默认值允许在打字错误等情况下出现无声的错误行为,因此违反了相同的原则,更不用说“显式优于隐式”,即,如果您想传递某些特殊值,则应将其写出来。在</p>
<p>您所指的PEP及其<code>if args: raise TypeError(...)</code>语义仅适用于具有不接受varargs的仅关键字参数的函数,并在参数列表中使用一个普通的<code>*</code>对其进行编码。有些函数可以接受有限数量的位置参数,并且可以从仅限关键字的参数中获益,但varargs对它们没有意义。对于这些,普通的<code>*</code>允许只使用关键字的参数,而不需要样板代码,并且在有人提供太多参数的情况下仍然通知程序员(这是一件好事,因为答案的第一部分列出了原因)。在</p>
<p>至于选择<code>TypeError</code>的原因:“参数数目错误”是静态语言中的编译器类型错误/类型不匹配</em>。我们在Python中没有对这些东西进行compiletime检查,但这仍然是一种“类型错误”。如果(在Python中,非正式的)类型签名显示“我接受两个参数”,而您提供了三个参数,那么这显然违反了该约定。<code>TypeError</code>不仅仅是<code>not isinstance(x, expected)</code>,就像其他很多与类型相关的主题一样(想想继承和“gets parent's stuff”与“is-a parent”)它是一个更广泛的概念。在</p>
<p>编辑回应你对静态类型比较的批评:考虑一元函数和二元函数不同,这不仅仅是静态类型系统的一个限制。即使在Python这样的语言中,它也非常有用,因为这两种语言还不够相似,不能“像走路一样嘎嘎嘎嘎地一样”(就像在duck类型中一样)——它们不能以相同的方式使用。(元编程是一个例外,它包装了大量的函数,由<code>*</code>和<code>**</code>解包运算符来处理。)它们碰巧都有一个事实,即它们是可调用的,但即使Python的内置对象层次结构没有创建许多只在数量和名称上不同的相同类。<code>type(f)</code>可能会说<code>function</code>,但这并不总是故事的结尾。在</p>