繁体   English   中英

为什么在尚未创建实例的情况下需要在__init__构造函数中指定self?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM