为什么我的类没有通过“def __int__”或“def _init_”初始化?为什么我会收到“不带参数”类型错误或属性错误?

Kar*_*tel 11 python initialization class typeerror magic-methods

如果您的问题作为此问题的重复项而被关闭,那是因为您有一个代码示例,其中包含以下任一内容:

class Example:
    def __int__(self, parameter):
        self.attribute = parameter
Run Code Online (Sandbox Code Playgroud)

或者:

class Example:
    def _init_(self, parameter):
        self.attribute = parameter
Run Code Online (Sandbox Code Playgroud)

当您随后尝试创建该类的实例时,会发生错误:

>>> Example("an argument")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Example() takes no arguments
Run Code Online (Sandbox Code Playgroud)

(在某些版本的 Python 中,错误可能会显示TypeError: object.__new__() takes no parameters。)

或者,该类的实例似乎缺少属性:

>>> class Example:
...     def __int__(self): # or _init_
...         self.attribute = 'value'

>>> Example().attribute
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Example' object has no attribute 'attribute'
Run Code Online (Sandbox Code Playgroud)

您可能还想知道:这些异常消息意味着什么,它们与问题有何关系?为什么没有更早地出现问题,例如类定义本身的问题?问题还可能如何体现?今后我该如何防范这个问题呢?


这是一个人为的规范问题,专门为避免新 Python 程序员编写的代码中两个最常见的印刷错误而创建。虽然由拼写错误引起的问题通常会因此而关闭,但在这种情况下有一些有用的事情需要解释,并且拥有重复的目标可以更快地关闭问题。我尝试将问题设计得易于搜索。

另请参见TypeError: __init__() should return None, not 'int'对于相反的问题 - 编写__init__而不是__int__尝试创建可以转换为整数的类时。

Kar*_*tel 6

这是因为代码有一个简单的印刷错误:该方法应该被命名__init__- 请注意拼写,并注意每一侧都有两个下划线。

异常消息的含义是什么?它们与问题有何关系?

正如人们可能猜到的那样,aTypeError是一个与某事物的类型有关的错误。在这种情况下,含义有点紧张:Python将这种错误类型用于函数调用,其中参数(为了调用函数、类构造函数或其他可调用对象而放置在中间的东西)无法正确分配给参数(使用语法编写函数时放置在之间的东西)。()()def

在出现a 的示例中TypeError, for 的类构造函数Example不带参数。为什么?因为它使用的是基本object构造函数,它不带参数。这只是遵循继承的正常规则:没有__init__本地定义,因此使用超类中的规则 - 在本例中object- 被使用。

同样,anAttributeError是与某事物的属性有关的错误。这非常简单: 的实例没有任何属性,因为构造函数(同样是由于拼写错误而产生的)没有设置属性。Example.attributeobject

为什么没有更早地出现问题,例如类定义本身的问题?

因为名称输入错误的方法在语法上仍然有效。SyntaxError在代码运行之前只能捕获语法错误(报告为)。Python 不会为命名的方法赋予任何特殊含义_init_(两边各有一个下划线),因此它不关心参数是什么。while__int__用于将类的实例转换为整数,并且除了 之外不应有任何参数self,但它在语法上仍然有效。

您的 IDE 可能会警告您有关__int__采用可疑参数(即除 之外的任何参数self)的方法。然而,a) 这并不能完全解决问题(见下文),b) IDE 可能一开始就帮助您弄错了(通过提出错误的自动完成建议)。

如今,打字_init_错误似乎已经不那么常见了。我的猜测是,人们过去在阅读排版不佳的书籍中的示例代码后会这样做。

问题还可能如何体现?

在成功创建实例(但未正确初始化)的情况下,稍后可能会发生任何类型的问题(取决于为什么需要正确初始化)。例如:

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
Run Code Online (Sandbox Code Playgroud)

如果您打算将该类转换为整数并且也__int__有意编写,则最后一个将优先:

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)
Run Code Online (Sandbox Code Playgroud)

将来我该如何预防这个问题?

没有灵丹妙药。__init__我发现,如果类需要一个方法,那么始终将(和/或__new__) 作为类中的第一个方法的约定会有所帮助。然而,校对或培训是无可替代的。