[英]Why do we need to specify self in __init__ constructor while the instance have not been created yet?
执行以下代码时:
class Test():
def __init__(self):
self.hi_there()
self.a = 5
def hi_there(self):
print(self.a)
new_object = Test()
new_object.hi_there()
我收到一个错误:
Traceback (most recent call last):
File "/root/a.py", line 241, in <module>
new_object = Test()
File "/root/a.py", line 233, in __init__
self.hello()
File "/root/a.py", line 238, in hello
print(self.a)
AttributeError: 'Test' object has no attribute 'a'
为什么在对象尚未初始化时需要在函数内部指定self
? 调用hi_there()
函数的可能性意味着该对象已经设置好,但是如果尚未初始化归因于此实例的其他变量怎么办? __init__
函数内部的self
是什么,如果它还不是“完整”对象呢?
显然,这部分代码有效:
class Test():
def __init__(self):
#self.hi_there()
self.a = 5
self.hi_there()
def hi_there(self):
print(self.a)
new_object = Test()
new_object.hi_there()
我来自C ++世界,在那里您必须在分配变量之前声明变量。 我完全理解您对self
的使用。 尽管我不了解如果self
对象没有完全初始化的话, __init__()
中self
的用途是什么。
没有魔术。 在调用__init__
,将创建对象并定义其方法,但是您可以设置所有实例属性并执行所有其他初始化。 如果您在__init__
查看执行:
def __init__(self):
self.hi_there()
self.a = 5
def hi_there(self):
print(self.a)
__init__
中发生的第一件事是hi_there
被调用。 该方法已经存在,那么函数调用的工作,我们掉进hi_there()
它不print(self.a)
但这是问题所在: self.a
尚未设置,因为这仅发生在__init__
的第二行中,但是我们从__init__
的第一行调用了hi_there
。 执行尚未到达设置self.a = 5
,因此在此分配之前发出的方法调用self.hi_there()
不可能使用self.a
这就是为什么您得到AttributeError
。
实际上,调用__init__
时已经创建了对象。 这就是为什么您需要self作为参数。 而且由于Python在内部工作的方式,您无法在没有self的情况下访问对象(请记住,它不必称为self,只要它是一个有效的名称,您就可以随意调用它不论其名称是什么,实例始终是方法的第一个参数。
事实是__init__
不会创建对象,而只是初始化它。 有一个叫做__new__
的类方法,它负责创建实例并返回它。 那就是创建对象的地方。
现在,对象何时获得它是a
属性。 这是在__init__
,但你可以访问它的内部方法__init__
。 我不完全了解对象的创建方式,但是一旦达到这一点,就已经设置了方法。 值不会发生这种情况,因此只有在__init__
定义它们之前,它们才可用。
基本上,Python创建对象,为其提供方法,然后为您提供实例,以便您可以初始化其属性。
编辑
我忘记提及的另一件事。 就像您定义__init__
,您也可以自己定义__new__
。 这不是很常见,但是在需要修改实际对象的创建时就可以这样做。 我仅在定义元类时才看到它( Python中的元类是什么? )。 在这种情况下,您可以定义的另一种方法是__call__
,使您获得更多控制权。
不确定您的意思,但是我想第一个代码示例应该调用hello()
函数而不是hi_there()
函数。
如果我错了,可以有人纠正我,但是在Python中,定义类或函数是动态的。 我的意思是,定义类或函数在运行时发生:这些是与其他语句一样执行的常规语句。
此语言功能允许执行诸如装饰功能行为之类的功能强大的功能,以增加额外的功能(请参见装饰器)。
因此,在创建Test
类的实例时,尝试在显式设置a
的值之前调用hello()
函数。 因此, Test
类是没有意识到它的a
属性。 必须顺序读取它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.