这是因为代码有一个简单的拼写错误:该方法应该被命名__init__
- 注意拼写,并注意有two两边都有下划线。
异常消息的含义是什么?它们与问题有何关系?
正如人们可能猜测的那样,一个TypeError
is an error这与type东西。在这种情况下,意思有点牵强:Pythonalso将此错误类型用于函数调用,其中论点 https://docs.python.org/3/glossary.html#term-argument(你放在中间的东西()
为了调用函数、类构造函数或其他callable https://docs.python.org/3/glossary.html#term-callable)无法正确分配给参数 https://docs.python.org/3/glossary.html#term-parameter(你放在之间的东西()
当使用def
句法)。
在示例中,其中TypeError
发生时,类构造函数为Example
不接受参数。为什么?因为它使用的是底座object
构造函数,它不带参数。这只是遵循正常的继承规则:没有__init__
本地定义的,因此来自超类的 - 在这种情况下,object
- 用来。
同样,一个AttributeError
is an error这与属性东西。这非常简单:实例Example
没有任何.attribute
属性,因为构造函数(同样来自object
由于拼写错误)没有设置一个。
为什么没有更早地出现问题,例如类定义本身的问题?
因为名称输入错误的方法在语法上仍然有效。仅语法错误(报告为SyntaxError
) 可以在代码运行之前捕获。 Python 没有为名为的方法分配任何特殊含义_init_
(两边各有一个下划线),所以它不关心参数是什么。尽管__int__ https://docs.python.org/3/reference/datamodel.html#object.__int__用于将类的实例转换为整数,并且除此之外不应有任何参数self
, 它还是句法上 valid.
您的 IDE 可能会警告您__int__
带有可疑参数的方法(即除了self
)。然而,a) 这并不能完全解决问题(见下文),b) IDE 可能一开始就帮助您弄错了(通过提出错误的自动完成建议)。
The _init_
如今,打字错误似乎已经不那么常见了。我的猜测是,人们过去在阅读排版不佳的书籍中的示例代码后会这样做。
问题还可能如何体现?
在实例创建成功(但未正确初始化)的情况下,任何类型的问题以后可能会发生(取决于why需要正确的初始化)。例如:
BOMB_IS_SET = True
class DefusalExpert():
def __int__(self):
global BOMB_IS_SET
BOMB_IS_SET = False
def congratulate(self):
if BOMB_IS_SET:
raise RuntimeError("everything blew up, gg")
else:
print("hooray!")
>>> d = DefusalExpert()
>>> d.congratulate()
Traceback (most recent call last):
...
RuntimeError: everything blew up, gg
如果您打算将该类转换为整数并且还写了__int__
故意地,last其中一个优先:
class LoneliestNumber:
def __int__(self):
return 1
def __int__(self): # was supposed to be __init__
self.two = "can be as bad"
>>> int(LoneliestNumber())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __int__ returned non-int (type NoneType)
将来我该如何预防这个问题?
没有灵丹妙药。我发现始终坚持这样的惯例会有所帮助__init__
(和/或__new__
) 作为类中的第一个方法(如果类需要)。然而,校对或培训是无可替代的。