为什么在Python函数调用中的参数过多/过少时会出现TypeError

问题描述

|| 我无法理解为什么当您提供不属于方法签名的参数时,Python为何会产生“ 0”的问题。 例:
>>> def funky():
...    pass
... 
>>> funky(500)
Traceback (most recent call last):
  File \"<stdin>\",line 1,in <module>
TypeError: funky() takes no arguments (1 given)
我以为,如果这是因为在无参数函数的范围内,
*args
是be3ѭ或
[]
,那是一个泄漏的抽象,因此我进行了查找。 我发现了什么 在PEP-3102上对
TypeError
进行页面搜索后,发现在一个上下文中出现ѭ0one的理由似乎是合理的,但我不理解该理由。 PEP的示例实质上说明该功能基本上是
if args: raise TypeError()
的快捷方式。在这种情况下,
args
一个非空列表,而不是同类型的空列表。如果我没记错的话,那确实是正当的理由,也许
ValueError
会更合适。但是,由于该示例是用Python编写的,因此这仍然是某种泄漏的抽象,这使得它更多地是某个用例的实现细节,而不是语言功能。像ѭ10here这样的声音在我看来更合适,这使我相信对于ѭ0sense为何有意义,我错过了一些明显的解释。     

解决方法

        该函数带有
n
个参数。您提供了
m
n != m
。这很可能是某人代码中的错误或某人对某些API的误解的症状。另外,我认为我们无法就有意义的,有用的语义达成一致,在这种情况下会发生什么。是否应该忽略多余的论点?这将使此类错误得以通过,并且由于“错误永远不会静默地传递”,因此这是不可接受的。同样,为省略的参数提供一些默认值会在出现错别字等情况下保持沉默,从而违反相同的原则,更不用说“显式优于隐式”,也就是说,如果您要传递一些特殊值,应该把它写出来。 您引用的PEP及其ѭ15语义仅适用于带有仅关键字参数的函数,这些参数不接受varargs,并在参数列表中使用普通的
*
进行编码。有些函数接受数量有限的位置参数,并且会从仅关键字的参数中受益,但varargs对它们没有意义。对于这些,存在普通的
*
允许仅关键字的参数而不需要样板代码,并且在有人提供太多参数的情况下仍会通知程序员(出于答案第一部分中列出的原因,这是一件好事)。 至于为什么选择“ 0”:\“错误的参数数量\”是静态语言中的编译时类型错误/类型不匹配。我们没有在Python中进行编译时检查,但是它仍然有点“类型错误”。如果(在Python中,非正式的)类型签名说“我有两个参数”,而您提供了三个,则显然违反了该合同。
TypeError
不仅意味着
not isinstance(x,expected)
,就像其他许多与打字相关的主题一样(只需考虑继承和“获取父母的东西”与“是父母”),它是一个更广泛的概念。 根据您对静态类型比较的批评,进行编辑:考虑与二进制函数不同的一元函数不仅是静态类型系统的固有限制。即使在像Python这样的语言中,这也是非常有用的,因为两者的相似度不足以被使用,“就像它们走路和敲打一样”(就像在鸭子输入法中一样)-它们不能在一样的方法。 (例外情况是元数据编程,它包装了可变的函数,由
*
**
拆包运算符处理。)它们碰巧共享一个事实,即它们是可调用的,但是即使Python的内置对象也不兼容。层次结构不会创建仅在Arity和名称上有所不同的众多相同类。
type(f)
可能是
function
,但这并不总是故事的结局。     ,        你说: def funky():   ... 因此,程序“ funky”不应带有任何“参数”。但是,当您使用该程序时,您说的是funky(argument),而funky不接受参数,因此导致了错误。要解决此问题,请使用; def funky(n):通过。