'self' 对象在方法 __init__ 中来自哪里?

where does the 'self' object comes from in the method __init__?

我正在学习python构造方法__init__让我很困惑。

class Test(object):
  def __init__(self):
    pass

众所周知,python 首先隐式传递一个表示对象本身的参数。它在普通成员函数中是可以接受的。但是让我感到困惑的是构造函数本身请求一个对象。 它看起来像下面的 C++ 代码。这段代码没有意义!参数thiz甚至在构造函数之前都没有退出!

class Test {
public:
  Test(Test *thiz);
};

所以,我的问题是,为什么 python 在构造函数 __init__ 中需要一个“不存在的”self 对象?

__init__ 的行为与 class 中的任何其他正常函数一样。如果定义了它,解释器会在特定时间调用它,但它没有什么特别之处。您可以随时自己调用它,就像常规方法一样。

这里有一些事实可以帮助您看清图片:

函数对象是非数据 descriptors in python. That means that function objects have a __get__ method, but not __set__. And if course they have a __call__ 实际 运行 函数的方法。

当您将 def 语句放入 class 主体时,它会创建一个常规函数,就像在其他地方一样。您可以通过查看 type(Test.__init__) 来了解这一点。要调用 Test.__init__,您必须手动传递 self 参数。

当您在 Test 的实例上调用 __init__ 时,奇迹就会发生。例如:

a = Test()
a.__init__()

这段代码实际上调用了两次 __init__(我们稍后会介绍)。显式的第二次调用不会将参数传递给该方法。这是因为当名称 __init__ 出现在 class 而不是实例中时, a.__init__ 具有特殊含义。如果 __init__ 是一个描述符,解释器将不会直接 ​​return 它,而是会对其调用 __get__ 并 return 结果。这称为绑定。

a.__init__()大致相当于type(a).__init__.__get__(a, None)()。调用 .__get__(a, None) return 是一个可调用对象,它是一个绑定方法。它就像一种特殊类型的偏函数,其中第一个位置参数设置为a。您可以通过检查 type(a.__init__).

来查看

self 参数作为第一个 positional 参数传递给方法。因此,它不必被称为 self。名称只是一个约定。 def __init__(this):def __init__(x) 也可以。

最后,我们来讨论一下 a = Test() 是如何调用 __init__ 的。 Class 对象可在 python 中调用。他们自己有一个class,叫做metaclass(通常只是type),它实际上定义了一个__call__方法。当您执行 Test() 时,您实际上是在调用 class.

默认情况下,class 的 __call__ 方法看起来像这样(非常粗略地近似):

def __call__(cls, *args, **kwargs):
    self = cls.__new__(cls, *args, **kwargs)
    if isinstance(self, cls):
        type(self).__init__(self, *args, **kwargs)

因此,新实例仅由 __new__ 创建,而不是由 __init__ 创建。后者是一个初始化器,而不是构造器或分配器。事实上,正如我之前提到的,您可以在大多数 class 上随心所欲地调用 __init__。值得注意的例外包括不可变的内置 classes,例如 tupleint.

作为初始化程序,__init__ 显然需要访问它正在初始化的对象。您的示例对 self 没有任何作用,但是设置实例属性并做一些事情来准备对象是非常标准的。对于像您这样的情况,根本不需要显式 __init__,因为会在基础 class 层次结构中找到缺失的函数。