简体   繁体   English

在python中调用超类的__init__时,Self的显式传递

[英]Explicit passing of Self when calling super class's __init__ in python

This question is in relation to posts at What does 'super' do in Python? 这个问题与“ super”在Python中的作用有关。 , How do I initialize the base (super) class? 如何初始化基类(超级)? , and Python: How do I make a subclass from a superclass? Python:如何从超类中生成子类? which describes two ways to initialize a SuperClass from within a SubClass as 它描述了两种从SubClass初始化SuperClass方法,如下所示:

class SuperClass:
    def __init__(self):
        return
    def superMethod(self):
        return


## One version of Initiation
class SubClass(SuperClass):
    def __init__(self):
        SuperClass.__init__(self)
    def subMethod(self):
        return

or 要么

class SuperClass:
    def __init__(self):
        return
    def superMethod(self):
        return

## Another version of Initiation
class SubClass(SuperClass):
    def __init__(self):
        super(SubClass, self).__init__()
    def subMethod(self):
        return

So I'm a little confused about needing to explicitly pass self as a parameter in SuperClass.__init__(self) and super(SubClass, self).__init__() . 所以我有点困惑,需要在SuperClass.__init__(self)super(SubClass, self).__init__() 显式传递self作为参数。 (In fact if I call SuperClass.__init__() I get the error (实际上,如果我调用SuperClass.__init__()收到错误消息

TypeError: __init__() missing 1 required positional argument: 'self'

). )。 But when calling constructors or any other class method (ie : 但是当调用构造函数或任何其他类方法时(即:

## Calling class constructor / initiation
c = SuperClass()
k = SubClass()

## Calling class methods
c.superMethod()
k.superMethod()
k.subMethod()

), The self parameter is passed implicitly . ),则隐式传递self参数。

My understanding of the self keyword is it is not unlike the this pointer in C++, whereas it provides a reference to the class instance. 我对self关键字的理解是,它与C ++中的this指针没有什么不同,但是它提供了对类实例的引用。 Is this correct? 这个对吗?

If there would always be a current instance (in this case SubClass ), then why does self need to be explicitly included in the call to SuperClass.__init__(self) ? 如果总是有一个当前实例(在这种情况下, SubClass ),那么为什么self需要被明确列入调用SuperClass.__init__(self)

Thanks 谢谢

This is simply method binding, and has very little to do with super . 这只是方法绑定,与super无关。 When you can x.method(*args) , Python checks the type of x for a method named method . 当您可以使用x.method(*args) ,Python将检查x的类型以查找名为method If it finds one, it "binds" the function to x , so that when you call it, x will be passed as the first parameter, before the rest of the arguments. 如果找到一个,它将“绑定”到x ,以便在您调用它时, x将作为第一个参数传递给其余参数。

When you call a (normal) method via its class, no such binding occurs. 当通过其类调用(常规)方法时,不会发生这种绑定。 If the method expects its first argument to be an instance (eg self ), you need to pass it in yourself. 如果该方法期望其第一个参数为实例(例如self ),则需要自己传递它。

The actual implementation of this binding behavior is pretty neat. 此绑定行为的实际实现非常简洁。 Python objects are "descriptors" if they have a __get__ method (and/or __set__ or __delete__ methods, but those don't matter for methods). 如果Python对象具有__get__方法(和/或__set____delete__方法,但它们与方法无关紧要),则它们是“描述符”。 When you look up an attribute like ab , Python checks the class of a to see if it has a attribute b that is a descriptor. 当你看像一个属性ab ,Python的检查类的a ,看它是否有一个属性b是一个描述符。 If it does, it translates ab into type(a).b.__get__(a, type(a)) . 如果是这样,它将ab转换为type(a).b.__get__(a, type(a)) If b is a function, it will have a __get__ method that implements the binding behavior I described above. 如果b是一个函数,它将具有实现上述绑定行为的__get__方法。 Other kinds of descriptors can have different behaviors. 其他类型的描述符可以具有不同的行为。 For instance, the classmethod decorator replaces a method with a special descriptor that binds the function the class, rather than the instance. 例如, classmethod装饰器用特殊的描述符替换方法,该描述符将函数绑定到类而不是实例。

Python's super creates special objects that handle attribute lookups differently than normal objects, but the details don't matter too much for this issue. Python的super创建了特殊对象,这些对象处理属性查找的方式与普通对象不同,但是对于该问题,细节并不重要。 The binding behavior of methods called through super is just like what I described in the first paragraph, so self gets passed automatically to the bound method when it is called. 通过super调用的方法的绑定行为就像我在第一段中所描述的那样,因此self会在调用时自动传递给绑定的方法。 The only thing special about super is that it may bind a different function than you'd get lookup up the same method name on self (that's the whole point of using it). super唯一的特别之处在于,它可能绑定的功能与您在self上查找相同的方法名称(这是使用它的全部目的)不同。

Because in SuperClass.__init__(self) , you're calling the method on the class, not the instance, so it cannot be passed implicitly. 因为在SuperClass.__init__(self) ,您是在类而不是实例上调用方法,所以它不能隐式传递。 Similarly you cannot just call SubClass.subMethod() , but you can call SubClass.subMethod(k) and it'll be equivalent to k.subMethod() . 同样,您不能只调用SubClass.subMethod() ,而可以调用SubClass.subMethod(k) ,它等效于k.subMethod() Similarly if self refers to a SubClass then self.__init__() means SubClass.__init__(self) , so if you want to call SuperClass.__init you have to call it directly. 同样,如果self引用SubClassself.__init__()表示SubClass.__init__(self) ,因此,如果要调用SuperClass.__init ,则必须直接调用它。

The answer is non-trivial and would probably warrant a good article. 答案是不平凡的,可能会推荐一篇好文章。 A very good explanation of how super() works is brilliantly given by Raymond Hettinger in a Pycon 2015 talk, available here and a related article . Raymond Hettinger在Pycon 2015演讲中出色地很好地解释了super()工作原理,可在此处以及相关文章中找到 I will attempt a short answer and if it is not sufficient I (and hopefully the community) will expand on it. 我将尝试一个简短的答案,如果不够的话,我(并希望社区)会对此进行扩展。 The answer has two key pieces: 答案有两个关键部分:

  • Python's super() needs to have an object on which the method being overridden is called, so it is explicitly passed with self. Python的super()需要有一个对象,在该对象上调用要重写的方法,因此它与self一起显式传递。 This is not the only possible implementation and in fact, in Python 3, it is no longer required that you pass the self instance. 这不是唯一可能的实现,实际上,在Python 3中,不再需要传递self实例。

  • Python super() is not like Java, or other compiled languages, super . Python super()不像Java或其他编译语言super Python's implementation is designed to support the multiple collaborative inheritance paradigm, as explained in Hettinger's talk. 如Hettinger的演讲中所述,Python的实现旨在支持多重协作继承范例。 This has an interesting consequence in Python: the method resolution in super() depends not only on the parent class, but on the children classes as well (consequence of multiple inheritance). 这在Python中产生了一个有趣的结果: super()的方法解析不仅取决于父类,还取决于子类(多重继承的结果)。 Note that Hettinger is using Python 3. 请注意,Hettinger使用的是Python 3。

The official Python 2.7 documentation on super is also a good source of information (better understood after watching the talk, in my opinion). 关于super Python 2.7官方文档也是一个很好的信息来源(我认为看完演讲后会更好理解)。

The following example might elucidate things: 以下示例可能会阐明问题:

class Example:
    def method(self):
        pass

>>> print(Example.method)
<unbound method Example.method>

>>> print(Example().method)
<bound method Example.method of <__main__.Example instance at 0x01EDCDF0>>

When a method is bound, the instance is passed implicitly. 绑定方法后,实例将隐式传递。 When a method is unbound, the instance needs to be passed explicitly. 当方法未绑定时,需要显式传递实例。

The other answers will definitely offer some more detail on the binding process, but I think it's worth showing the above snippet. 其他答案肯定会提供有关绑定过程的更多详细信息,但是我认为值得展示以上片段。

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

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