简体   繁体   English

__init__ 方法中的“自我”object 来自哪里?

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

I'm learning python and the construct method __init__ makes me confused.我正在学习 python 并且构造方法__init__让我感到困惑。

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

As known, python implicitly pass a parameter representing the object itself at the first place.众所周知,python 首先隐式传递代表 object 本身的参数。 It is acceptable in common member functions.在普通成员函数中是可以接受的。 But what makes me confused is that the constructor requests an object itself.但让我感到困惑的是,构造函数本身请求了一个 object。 It looks like the c++ code below.它看起来像下面的 c++ 代码。 This code does not make sense!这段代码没有意义! The parameter thiz does not even exit before the constructor!参数thiz甚至不会在构造函数之前退出!

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

So, my question is, why python needs a "non-existent" self object in constructor __init__ ?所以,我的问题是,为什么 python 在构造函数__init__中需要一个“不存在的” self object ?

__init__ behaves like any other normal function in a class. __init__的行为类似于 class 中的任何其他正常 function。 It gets called by the interpreter at a special time if it is defined, but there is nothing special about it.如果它被定义,它会在一个特殊的时间被解释器调用,但它并没有什么特别之处。 You can call it any time yourself, just like a regular method.您可以自己随时调用它,就像常规方法一样。

Here are some facts to help you see the picture:这里有一些事实可以帮助您查看图片:

Function objects are non-data descriptors in python. Function 对象是 python 中的非数据描述符 That means that function objects have a __get__ method, but not __set__ .这意味着 function 对象具有__get__方法,但没有__set__ And if course they have a __call__ method to actually run the function.如果他们当然有一个__call__方法来实际运行 function。

When you put a def statement in a class body, it creates a regular function, just like it would elsewhere.当您将def语句放入 class 主体时,它会创建一个常规 function,就像在其他地方一样。 You can see this by looking at type(Test.__init__) .您可以通过查看type(Test.__init__)来看到这一点。 To call Test.__init__ , you would have to manually pass in a self parameter.要调用Test.__init__ ,您必须手动传入一个self参数。

The magic happens when you call __init__ on an instance of Test .当您在Test的实例上调用__init__时,魔法就会发生。 For example:例如:

a = Test()
a.__init__()

This code actually calls __init__ twice (which we'll get into momentarily).这段代码实际上调用了__init__两次(我们稍后会介绍)。 The explicit second call does not pass in a parameter to the method.显式的第二次调用不会将参数传递给该方法。 That's because a.__init__ has special meaning when the name __init__ is present in the class but not the instance.这是因为当名称__init__出现在 class 中而不是实例中时, a.__init__具有特殊含义。 If __init__ is a descriptor, the interpreter will not return it directly, but rather will call __get__ on it and return the result.如果__init__是一个描述符,解释器不会直接返回它,而是会在它上面调用__get__并返回结果。 This is called binding.这称为绑定。

a.__init__() is roughly equivalent to type(a).__init__.__get__(a, None)() . a.__init__()大致相当于type(a).__init__.__get__(a, None)() The call .__get__(a, None) returns a callable object that is a bound method.调用.__get__(a, None)返回作为绑定方法的可调用 object。 It is like a special type of partial function, in which the first positional parameter is set to a .就像偏 function 的一种特殊类型,其中第一个位置参数设置a . You can see this by checking type(a.__init__) .您可以通过检查type(a.__init__)看到这一点。

The self parameter is passed to methods as the first positional parameter. self参数作为第一个位置参数传递给方法。 As such, it does not have to be called self .因此,它不必称为self The name is just a convention.这个名字只是一个约定。 def __init__(this): or def __init__(x) would work just as well. def __init__(this):def __init__(x)也可以。

Finally, let's discuss how a = Test() ends up calling __init__ .最后,让我们讨论一下a = Test()是如何调用__init__的。 Class objects are callable in python. Class 对象可在 python 中调用。 They have a class themselves, called a metaclass (usually just type ), which actually defines a __call__ method.他们自己有一个 class ,称为元类(通常只是type ),它实际上定义了一个__call__方法。 When you do Test() , you are literally calling the class.当您执行Test()时,您实际上是在调用 class。

By default, the __call__ method of a class looks something (very roughly approximately) like this:默认情况下,class 的__call__方法看起来(非常近似)如下所示:

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

So a new instance is only created by __new__ , not __init__ .所以一个新实例只能由__new__创建,而不是__init__ The latter is an initializer, not a constructor or allocator.后者是初始化器,而不是构造器或分配器。 In fact, as I mentioned before, you can call __init__ as often as you like on most classes.事实上,正如我之前提到的,您可以在大多数类中尽可能频繁地调用__init__ Notable exceptions include immutable built-in classes like tuple and int .值得注意的例外包括不可变的内置类,如tupleint

As an initializer, __init__ obviously needs access to the object it is initializing.作为初始化器, __init__显然需要访问它正在初始化的 object。 Your example does nothing with self , but it is pretty standard to set instance attributes and do something things to prep the object.您的示例对self没有任何作用,但设置实例属性并做一些事情来准备 object 是非常标准的。 For cases like yours, an explicit __init__ is not necessary at all, since a missing function will be found in the base class hierarchy.对于像您这样的情况,根本不需要显式的__init__ ,因为在基本 class 层次结构中会发现缺少的 function 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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