[英]Why isn't my class initialized by "def __int__" or "def _init_"? Why do I get a "takes no arguments" TypeError, or an AttributeError?
If your question was closed as a duplicate of this, it is because you had a code sample including something along the lines of either:如果您的问题与此重复,那是因为您有一个代码示例,其中包含以下任一内容:
class Example:
def __int__(self, parameter):
self.attribute = parameter
or:或者:
class Example:
def _init_(self, parameter):
self.attribute = parameter
When you subsequently attempt to create an instance of the class, an error occurs:当您随后尝试创建 class 的实例时,会发生错误:
>>> Example("an argument")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Example() takes no arguments
Alternately, instances of the class seem to be missing attributes:或者, class 的实例似乎缺少属性:
>>> 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'
This is because the code has a simple typographical error : the method should instead be named __init__
- note the spelling, and note that there are two underscores on each side.这是因为代码有一个简单的印刷错误:该方法应该命名为
__init__
- 注意拼写,并注意每边有两个下划线。
You might also wonder: what do these exception messages mean, and how do they relate to the problem?您可能还想知道:这些异常消息是什么意思,它们与问题有什么关系? Why didn't a problem occur earlier, for example, with the class definition itself?
为什么之前没有出现问题,例如 class 定义本身? How else might the problem manifest?
问题还可能如何表现? How can I guard against this problem in the future?
以后如何防范这个问题?
This is an artificial canonical duplicate created specifically to head off two of the most common typographical errors in code written by new Python programmers.这是一个人工的规范副本,专门用于防止新 Python 程序员编写的代码中两个最常见的印刷错误。 While questions caused by a typo are normally closed for that reason, there are some useful things to explain in this case, and having a duplicate target allows for closing questions faster.
虽然由拼写错误引起的问题通常会因此而关闭,但在这种情况下有一些有用的东西需要解释,并且有一个重复的目标可以更快地关闭问题。 I have tried to design the question to be easy to search for.
我试图将问题设计为易于搜索。
As one might guess, a TypeError
is an Error
that has to do with the Type
of something.有人可能会猜到,
TypeError
是与某事物的Type
有关的Error
。 In this case, the meaning is a bit strained: Python also uses this error type for function calls where the arguments (the things you put in between ()
in order to call a function, class constructor or other "callable") cannot be properly assigned to the parameters (the things you put between ()
when writing a function using the def
syntax).在这种情况下,含义有点紧张:Python也将此错误类型用于函数调用,其中参数(您在
()
之间放置的东西以调用函数、类构造函数或其他“可调用”)不能正确分配给参数(使用def
语法编写函数时放在()
之间的东西)。
In the examples where a TypeError
occurs, the class constructor for Example
does not take arguments.在发生
TypeError
的示例中, Example
的类构造函数不带参数。 Why?为什么? Because it is using the base
object
constructor , which does not take arguments.因为它使用了不带参数的基础
object
构造函数。 That is just following the normal rules of inheritance: there is no __init__
defined locally, so the one from the superclass - in this case, object
- is used.这只是遵循常规的继承规则:本地没有定义
__init__
,因此使用了超类中的那个——在这种情况下,是object
。
Similarly, an AttributeError
is an Error
that has to do with the Attribute
s of something.同样,
AttributeError
是与某物的Attribute
相关的Error
。 This is quite straightforward: the instance of Example
doesn't have any .attribute
attribute, because the constructor (which, again, comes from object
due to the typo) did not set one.这很简单: Example 的
Example
没有任何.attribute
属性,因为构造函数(同样,由于错字而来自object
)没有设置一个。
Because the method with a wrongly typed name is still syntactically valid.因为名称输入错误的方法在语法上仍然有效。 Only syntax errors (reported as
SyntaxError
; yes, it's an exception, and yes, there are valid uses for it in real programs) can be caught before the code runs.在代码运行之前,只能捕获语法错误(报告为
SyntaxError
;是的,这是一个异常,是的,它在实际程序中有有效的用途)可以被捕获。 Python does not assign any special meaning to methods named _init_
(with one underscore on each side), so it does not care what the parameters are. Python 没有为名为
_init_
的方法赋予任何特殊含义(每边有一个下划线),因此它不关心参数是什么。 While __int__
is used for converting instances of the class to integer, and shouldn't have any parameters besides self
, it is still syntactically valid.虽然
__int__
用于将类的实例转换为整数,并且除了self
之外不应有任何参数,但它在语法上仍然有效。
Your IDE might be able to warn you about an __int__
method that takes suspicious parameters (ie, anything besides self
).您的 IDE 可能会就带有可疑参数的
__int__
方法(即除self
之外的任何参数)向您发出警告。 However, a) that doesn't completely solve the problem (see below), and b) the IDE might have helped you get it wrong in the first place (by making a bad autocomplete suggestion).但是,a) 这并不能完全解决问题(见下文),并且 b) IDE 可能一开始就帮助您弄错了(通过提出错误的自动完成建议)。
The _init_
typo seems to be much less common nowadays. _init_
错字现在似乎不太常见了。 My guess is that people used to do this after reading example code out of books with poor typesetting.我的猜测是,人们过去常常在阅读排版不佳的书籍中的示例代码后这样做。
In the case where an instance is successfully created (but not properly initialized), any kind of problem could potentially happen later (depending on why proper initialization was needed).在成功创建实例(但未正确初始化)的情况下,以后可能会发生任何类型的问题(取决于需要正确初始化的原因)。 For example:
例如:
BOMB_IS_SET = True
class DefusalExpert():
def __int__(self):
global BOMB_IS_SET
BOMB_IS_SET = False
def congratulate(self):
global BOMB_IS_SET
if BOMB_IS_SET:
raise RuntimeError("everything blew up, gg")
else:
print("hooray!")
If you intend for the class to be convertible to integer and also wrote __int__
deliberately, the last one will take precedence:如果您打算将该类转换为整数并且还故意写了
__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)
(Note that __int__
will not be used implicitly to convert instances of the class to an index for a list or tuple. That's done by __index__
.) (请注意,
__int__
不会隐式用于将类的实例转换为列表或元组的索引。这是由__index__
完成的。)
There is no magic bullet.没有灵丹妙药。 I find it helps a little to have the convention of always putting
__init__
(and/or __new__
) as the first method in a class, if the class needs one.如果类需要一个方法,我发现始终将
__init__
(和/或__new__
)作为类中的第一个方法的约定会有所帮助。 However, there is no substitute for proofreading, or for training.但是,校对或培训是无可替代的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.